Opened 11 years ago
Closed 8 years ago
#6167 closed Bugs (wontfix)
Assignment from a temporary of a class containing boost::unordered_map members fails with GNU GCC.
Reported by: | Owned by: | Ion Gaztañaga | |
---|---|---|---|
Milestone: | To Be Determined | Component: | unordered |
Version: | Boost 1.48.0 | Severity: | Problem |
Keywords: | Cc: |
Description
With boost 1.48.0 the following code does not compile anymore:
#include <boost/unordered_map.hpp>
struct A {
boost::unordered_map<int, int> m;
};
void Test() {
A a;
a = A();
}
GCC 4.6.1 & GCC 4.1.2 say:
11:8: error: no match for ‘operator=’ in ‘a = A()’
11:8: note: candidate is:
4:8: note: A& A::operator=(A&)
4:8: note: no known conversion for argument 1 from ‘A’ to ‘A&’
When GCC 4.6.1 is set as C++11 compiler (-std=c++0x), it compiles without errors.
Change History (8)
comment:1 by , 11 years ago
Owner: | changed from | to
---|
comment:2 by , 11 years ago
I see Boost.Move tells me how to work around it. Note also that assignment from map_list_of can't be done anymore (although that doesn't work at all when -std=c++0x, but that's not an unordered bug). So this will now also fail:
boost::unordered_map<int, int> m;
m = boost::assign::map_list_of(1, 1)(2, 2);
I guess the only good way around it all ... is to provide two versions of all unordered containers (with & without move). So one in 'boost' and one in 'boost::container'.
If that isn't going to happen and if this is not considered a bug, but a limitation (or nuisance), I'd say these breaking changes should be well documented @ Boost.Unordered.
comment:3 by , 11 years ago
I don't see why assignments from map_list_of can't be done. map_list_of returns a container by value and that value can be assigned. Or am I missing something?
comment:4 by , 11 years ago
this works:
boost::unordered_map<int, int> m = boost::assign::map_list_of(1, 1)(2, 2);
this doesn't:
boost::unordered_map<int, int> m;
m = boost::assign::map_list_of(1, 1)(2, 2);
with the follow errors:
move.hpp:233:7: error: ‘boost::rv<T>::~rv() [with T = boost::unordered::unordered_map<int, int>]’ is private
test.cpp:14:28: error: within this context
In file included from test.cpp:6:0:
move.hpp: In member function ‘boost::assign_detail::generic_list<T>::operator Container() const [with Container = boost::rv<boost::unordered::unordered_map<int, int> >, T = std::pair<int, int>]’:
test.cpp:14:28: instantiated from here
move.hpp:233:7: error: ‘boost::rv<T>::~rv() [with T = boost::unordered::unordered_map<int, int>]’ is private
list_of.hpp:436:81: error: within this context
move.hpp:234:7: error: ‘boost::rv<T>::rv(const boost::rv<T>&) [with T = boost::unordered::unordered_map<int, int>, boost::rv<T> = boost::rv<boost::unordered::unordered_map<int, int> >]’ is private
list_of.hpp:436:81: error: within this context
In file included from test.cpp:6:0:
move.hpp: In member function ‘Container boost::assign_detail::converter<DerivedTAssign, Iterator>::convert_to_container() const [with Container = boost::rv<boost::unordered::unordered_map<int, int> >, DerivedTAssign = boost::assign_detail::generic_list<std::pair<int, int> >, Iterator = std::_Deque_iterator<std::pair<int, int>, std::pair<int, int>&, std::pair<int, int>*>]’:
list_of.hpp:436:81: instantiated from ‘boost::assign_detail::generic_list<T>::operator Container() const [with Container = boost::rv<boost::unordered::unordered_map<int, int> >, T = std::pair<int, int>]’
test.cpp:14:28: instantiated from here
move.hpp:233:7: error: ‘boost::rv<T>::~rv() [with T = boost::unordered::unordered_map<int, int>]’ is private
list_of.hpp:142:54: error: within this context
move.hpp:234:7: error: ‘boost::rv<T>::rv(const boost::rv<T>&) [with T = boost::unordered::unordered_map<int, int>, boost::rv<T> = boost::rv<boost::unordered::unordered_map<int, int> >]’ is private
list_of.hpp:142:54: error: within this context
list_of.hpp: In member function ‘Container boost::assign_detail::converter<DerivedTAssign, Iterator>::convert(const Container*, boost::assign_detail::default_type_tag) const [with Container = boost::rv<boost::unordered::unordered_map<int, int> >, DerivedTAssign = boost::assign_detail::generic_list<std::pair<int, int> >, Iterator = std::_Deque_iterator<std::pair<int, int>, std::pair<int, int>&, std::pair<int, int>*>]’:
list_of.hpp:142:54: instantiated from ‘Container boost::assign_detail::converter<DerivedTAssign, Iterator>::convert_to_container() const [with Container = boost::rv<boost::unordered::unordered_map<int, int> >, DerivedTAssign = boost::assign_detail::generic_list<std::pair<int, int> >, Iterator = std::_Deque_iterator<std::pair<int, int>, std::pair<int, int>&, std::pair<int, int>*>]’
list_of.hpp:436:81: instantiated from ‘boost::assign_detail::generic_list<T>::operator Container() const [with Container = boost::rv<boost::unordered::unordered_map<int, int> >, T = std::pair<int, int>]’
test.cpp:14:28: instantiated from here
list_of.hpp:163:46: error: no matching function for call to ‘boost::rv<boost::unordered::unordered_map<int, int> >::rv(boost::assign_detail::converter<boost::assign_detail::generic_list<std::pair<int, int> >, std::_Deque_iterator<std::pair<int, int>, std::pair<int, int>&, std::pair<int, int>*> >::iterator, boost::assign_detail::converter<boost::assign_detail::generic_list<std::pair<int, int> >, std::_Deque_iterator<std::pair<int, int>, std::pair<int, int>&, std::pair<int, int>*> >::iterator)’
list_of.hpp:163:46: note: candidates are:
move.hpp:234:7: note: boost::rv<T>::rv(const boost::rv<T>&) [with T = boost::unordered::unordered_map<int, int>, boost::rv<T> = boost::rv<boost::unordered::unordered_map<int, int> >]
move.hpp:234:7: note: candidate expects 1 argument, 2 provided
move.hpp:232:7: note: boost::rv<T>::rv() [with T = boost::unordered::unordered_map<int, int>]
move.hpp:232:7: note: candidate expects 0 arguments, 2 provided
comment:5 by , 11 years ago
Boost.Unordered is not the place for documenting this, since I don't have a good understanding of the problem and don't wish to waste any time trying to. A link to the explanation in the move documentation is the best I can do. Which is actually a better solution from a maintenance point of view, as information written in unordered is likely to get dated if the situation change. Even if someone else volunteered to write it (unlikely as that is), they probably wouldn't be able to keep it up to date.
I suppose Move could offer a quickbook file with some generic info to be included (using templates to insert appropriate names). I'm not sure how well that would work in practice though. Dropping a bunch of standard text into the middle of a document can have odd results.
comment:7 by , 10 years ago
In what seems to be either the same or related issue, on some versions of gcc (llvm-gcc-4.2 from Xcode on OS X, but not g++-4.1.2 in Linux) the following also does not compile (using the same 'struct A' from above):
A a1, a2; std::swap(a1, a2); Compile error inside generic non-specialized std::swap() when assigning "const Tmp tmp = ...;".
On the other hand the originally described problem (simply 'A a; a = A();') occurs on both compilers I mentioned.
comment:8 by , 8 years ago
Resolution: | → wontfix |
---|---|
Status: | new → closed |
After three years, I'm afraid the best thing to do is to close the issue with wontfix.
That's a limitation of Boost.Move's move emulation:
http://www.boost.org/doc/html/move/emulation_limitations.html#move.emulation_limitations.assignment_operator
I don't know if there's a good way round it. I'm reassigning to Ion to see if he's got any suggestions?