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: Geurt Vos <geurt.vos@…> 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 anonymous, 11 years ago

Owner: changed from Daniel James to Ion Gaztañaga

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?

comment:2 by Geurt Vos <geurt.vos@…>, 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 Ion Gaztañaga, 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 Geurt Vos <geurt.vos@…>, 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 Daniel James, 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:6 by Ion Gaztañaga, 11 years ago

I', afraid Boost.Assign will need some tweak to support Boost.Move

comment:7 by yurik@…, 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 Ion Gaztañaga, 8 years ago

Resolution: wontfix
Status: newclosed

After three years, I'm afraid the best thing to do is to close the issue with wontfix.

Note: See TracTickets for help on using tickets.