Modify

Ticket #6167 (new Bugs)

Opened 2 years ago

Last modified 23 months ago

Assignment from a temporary of a class containing boost::unordered_map members fails with GNU GCC.

Reported by: Geurt Vos <geurt.vos@…> Owned by: igaztanaga
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.

Attachments

Change History

comment:1 Changed 2 years ago by anonymous

  • Owner changed from danieljames to igaztanaga

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 Changed 2 years ago by Geurt Vos <geurt.vos@…>

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 Changed 2 years ago by igaztanaga

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 Changed 2 years ago by Geurt Vos <geurt.vos@…>

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 Changed 2 years ago by danieljames

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 Changed 2 years ago by igaztanaga

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

comment:7 Changed 23 months ago by yurik@…

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.

View

Add a comment

Modify Ticket

Change Properties
<Author field>
Action
as new
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.