[libc++] clang / libc++ fail to compile the code with boost

Hi,

I bet the problem is in boost implementation butI’m not 100% sure whether the issue is really on boost side or not.

Compiling the following code

$ cat boost_thread.cpp

#include <boost/thread.hpp>

int main()
{
return 0;
}

$ clang++ -stdlib=libc++ ./boost_thread.cpp

In file included from ./boost_thread.cpp:1:
In file included from /usr/include/boost/thread.hpp:24:
In file included from /usr/include/boost/thread/future.hpp:14:
In file included from /usr/include/boost/exception_ptr.hpp:9:
In file included from /usr/include/boost/exception/detail/exception_ptr.hpp:19:
In file included from /usr/include/boost/exception/info.hpp:15:
In file included from /usr/include/boost/exception/to_string_stub.hpp:15:
In file included from /usr/include/boost/exception/detail/object_hex_dump.hpp:14:
/usr/include/boost/exception/detail/type_info.hpp:53:9: error: cannot define the implicit default assignment operator for
‘boost::exception_detail::type_info_’, because non-static reference member ‘type_’ can’t use default assignment operator
type_info_
^
/usr/include/c++/v1/__tree:1244:35: note: in instantiation of member function ‘std::_1::pair<boost::exception_detail::type_info,
boost::shared_ptrboost::exception_detail::error_info_base >::operator=’ requested here
__cache->_value = *__first;
^
/usr/include/c++/v1/__tree:1185:9: note: in instantiation of function template specialization
'std::__1::__tree<std::_1::pair<boost::exception_detail::type_info, boost::shared_ptrboost::exception_detail::error_info_base >,
std::__1::_map_value_compare<boost::exception_detail::type_info, boost::shared_ptrboost::exception_detail::error_info_base,
std::__1::lessboost::exception_detail::type_info_, true>, std::__1::allocator<std::_1::pair<boost::exception_detail::type_info,
boost::shared_ptrboost::exception_detail::error_info_base > >

::__assign_multi<std::__1::__tree_const_iterator<std::_1::pair<boost::exception_detail::type_info,
boost::shared_ptrboost::exception_detail::error_info_base >, const std::__1::__tree_node<std::_1::pair<boost::exception_detail::type_info,
boost::shared_ptrboost::exception_detail::error_info_base >, void *> *, long> >’ requested here
__assign_multi(__t.begin(), __t.end());
^
/usr/include/c++/v1/map:760:21: note: in instantiation of member function ‘std::__1::__tree<std::_1::pair<boost::exception_detail::type_info,
boost::shared_ptrboost::exception_detail::error_info_base >, std::__1::_map_value_compare<boost::exception_detail::type_info,
boost::shared_ptrboost::exception_detail::error_info_base, std::__1::lessboost::exception_detail::type_info_, true>,
std::__1::allocator<std::_1::pair<boost::exception_detail::type_info, boost::shared_ptrboost::exception_detail::error_info_base > > >::operator=’
requested here
_tree = __m._tree;
^
/usr/include/boost/exception/info.hpp:160:26: note: in instantiation of member function ‘std::_1::map<boost::exception_detail::type_info,
boost::shared_ptrboost::exception_detail::error_info_base, std::_1::lessboost::exception_detail::type_info_,
std::1::allocator<std::1::pair<const boost::exception_detail::type_info, boost::shared_ptrboost::exception_detail::error_info_base > >
::operator=’ requested here
c->info
= info
;
^
/usr/include/boost/exception/detail/type_info.hpp:55:41: note: declared here
detail::sp_typeinfo const & type
;
^
/usr/include/c++/v1/utility:247:15: note: implicit default copy assignment operator for 'boost::exception_detail::type_info
’ first required here
first = __p.first;
^
1 error generated.

Testcase without boost:

#include <map>
struct A { int& x; explicit A(int); public: bool operator<(const A&
other) const {return x < other.x; }};
void f(A* x) { std::map<A, int> y, z; z = y; }

This looks like a boost bug to me... as far as I can tell, the Key
type of an std::map is required to be assignable if you're assigning
one map to another (although the implementation isn't required to
actually use that assignment operator).

-Eli

Err, I take that back... I really have no clue whether it's required.

-Eli

C++0x [container.requirements.general] is fairly clear that assigning a container requires the element type to be move assignable. This is a Boost bug.

  - Doug

Hi,
I bet the problem is in boost implementation but
I'm not 100% sure whether the issue is really on boost side or not.

<snip>

Testcase without boost:

#include <map>
struct A { int& x; explicit A(int); public: bool operator<(const A&
other) const {return x < other.x; }};
void f(A* x) { std::map<A, int> y, z; z = y; }

This looks like a boost bug to me... as far as I can tell, the Key
type of an std::map is required to be assignable if you're assigning
one map to another (although the implementation isn't required to
actually use that assignment operator).

C++0x [container.requirements.general] is fairly clear that assigning a container requires the element type to be move assignable. This is a Boost bug.

Strongly agree. Especially if you s/copy/move. :wink: And include the reference [associative.reqmts]/p7:

The associative containers meet all the requirements of Allocator-aware containers (23.2.1), except that for map and multimap, the requirements placed on value_type in Table 96 apply instead to key_type and mapped_type. [Note: For example, in some cases key_type and mapped_type are required to be CopyAssignable even though the associated value_type, pair<const key_type, mapped_type>, is not CopyAssignable. —endnote]

To be fair to boost, this was at best unspecified in C++03 and no implementation of map took advantage of it (erase/insert was/is a common algorithm for assignment). libc++ is probably the first std::lib to recycle nodes under associative container assignment. This can be a huge performance win for copy assignment.

Howard

Thank you all for your comments and diagnosis.
It sounds like I have to file a bug report to the boost developers.

Cheers,

Ryuta