C ++ 11 compilation error with g ++ 4.6 and boost :: unordered_map

I have a piece of C ++ code that fails with a compilation error if it is not running in C ++ 11 mode, but I cannot understand why this would be so, since the code does not (explicitly) use C + + 11:

#include <vector> #include <map> #include <boost/unordered_map.hpp> struct SomeStruct { boost::unordered_map<int, int> intMap; }; int main(int argc, const char* argv[]) { std::vector<SomeStruct> vals; vals.resize(100); } 

When compiling this on a 64-bit Ubuntu 12.04 machine with gcc 4.6.3-1ubuntu5 and raising 1.48:

 g++ test.cpp 

then I get this compilation error:

 In file included from /usr/include/c++/4.6/vector:61:0, from test.cpp:1: /usr/include/c++/4.6/bits/stl_algobase.h: In function 'typename __gnu_cxx::__enable_if<(! std::__is_scalar<_Tp>::__value), void>::__type std::__fill_a(_ForwardIterator, _ForwardIterator, const _Tp&) [with _ForwardIterator = SomeStruct*, _Tp = SomeStruct, typename __gnu_cxx::__enable_if<(! std::__is_scalar<_Tp>::__value), void>::__type = void]': /usr/include/c++/4.6/bits/stl_algobase.h:722:7: instantiated from 'void std::fill(_ForwardIterator, _ForwardIterator, const _Tp&) [with _ForwardIterator = SomeStruct*, _Tp = SomeStruct]' /usr/include/c++/4.6/bits/vector.tcc:397:5: instantiated from 'void std::vector<_Tp, _Alloc>::_M_fill_insert(std::vector<_Tp, _Alloc>::iterator, std::vector<_Tp, _Alloc>::size_type, const value_type&) [with _Tp = SomeStruct, _Alloc = std::allocator<SomeStruct>, std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<SomeStruct*, std::vector<SomeStruct> >, typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer = SomeStruct*, std::vector<_Tp, _Alloc>::size_type = long unsigned int, std::vector<_Tp, _Alloc>::value_type = SomeStruct]' /usr/include/c++/4.6/bits/stl_vector.h:944:9: instantiated from 'void std::vector<_Tp, _Alloc>::insert(std::vector<_Tp, _Alloc>::iterator, std::vector<_Tp, _Alloc>::size_type, const value_type&) [with _Tp = SomeStruct, _Alloc = std::allocator<SomeStruct>, std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<SomeStruct*, std::vector<SomeStruct> >, typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer = SomeStruct*, std::vector<_Tp, _Alloc>::size_type = long unsigned int, std::vector<_Tp, _Alloc>::value_type = SomeStruct]' /usr/include/c++/4.6/bits/stl_vector.h:632:4: instantiated from 'void std::vector<_Tp, _Alloc>::resize(std::vector<_Tp, _Alloc>::size_type, std::vector<_Tp, _Alloc>::value_type) [with _Tp = SomeStruct, _Alloc = std::allocator<SomeStruct>, std::vector<_Tp, _Alloc>::size_type = long unsigned int, std::vector<_Tp, _Alloc>::value_type = SomeStruct]' test.cpp:12:18: instantiated from here /usr/include/c++/4.6/bits/stl_algobase.h:676:2: error: no match for 'operator=' in '* __first = __value' /usr/include/c++/4.6/bits/stl_algobase.h:676:2: note: candidate is: test.cpp:5:8: note: SomeStruct& SomeStruct::operator=(SomeStruct&) test.cpp:5:8: note: no known conversion for argument 1 from 'const SomeStruct' to 'SomeStruct&' 

This compiles when you enable C ++ 11 support in gcc:

 g++ -std=c++0x test.cpp 

Can anyone explain why this only works in C ++ 11 mode?

Edit:

Steps to play using Vagrant:

 vagrant init precise64 vagrant up vagrant ssh sudo apt-get install -y build-essential libboost1.48-all-dev echo "#include <vector> #include <map> #include <boost/unordered_map.hpp> struct SomeStruct { boost::unordered_map<int, int> intMap; }; int main(int argc, const char* argv[]) { std::vector<SomeStruct> vals; vals.resize(100); }" > test.cpp g++ test.cpp 
+4
source share
1 answer

The copy assignment operator boost::unordered_map declared as:

 unordered_map& operator=(unordered_map &t) 

which, in turn, calls (C ++ 98 12.8 [# 10]) the implicit copy assignment operator SomeStruct , which should be declared as:

 SomeStruct &operator= (SomeStruct &); 

Adding an explicit copy assignment operator

 SomeStruct &operator= (const SomeStruct &x) { intMap = x.intMap; return *this; } 

solves the problem and it works, causing various overloads unordered_map::operator= .

This issue has been fixed in Boost 1.52. which declares the statement as follows:

 unordered_map& operator=(unordered_map const& x); 
+3
source

All Articles