I'm trying to get a deeper understanding of C++ by reading the C++14 standard along with the source of libc++ and libstdc++. The implementation of various type_traits
items varies between the two, particularly is_move_assignable
, and I'm trying to figure out which of them is "more correct."
libc++:
template <class _Tp> struct is_move_assignable
: public is_assignable<typename add_lvalue_reference<_Tp>::type,
const typename add_rvalue_reference<_Tp>::type> {};
libstdc++:
template<typename _Tp, bool = __is_referenceable<_Tp>::value>
struct __is_move_assignable_impl;
template<typename _Tp>
struct __is_move_assignable_impl<_Tp, false>
: public false_type { };
template<typename _Tp>
struct __is_move_assignable_impl<_Tp, true>
: public is_assignable<_Tp&, _Tp&&>
{ };
template<typename _Tp>
struct is_move_assignable
: public __is_move_assignable_impl<_Tp>
{ };
The standard states:
For a referenceable type
T
, the same result asis_assignable<T&, T&&>::value
, otherwisefalse
.
The first thing I noted is that libc++ applies const
to the second template parameter, which doesn't seem right since the move assignment operator takes a non-const rvalue. libstdc++ also uses __is_referenceable
, which follows the wording of the standard, but libc++ doesn't. Is that requirement covered by libc++'s use of add_lvalue_reference
and add_rvalue_reference
, which both enforce __is_referenceable
on their own?
I would really appreciate any insight into why each project chose their solutions!
Thanks! Any idea why the authors might have added
const
, then?
My best guess is temporary (hopefully) insanity:
https://github.com/llvm-mirror/libcxx/commit/6063ec176d5056683d6ddd310c2e3a8f1c7e1b46#diff-48f5ee43879b5ad38888f0a6ead10113R1245
;-)
I removed the const
and ran the current unit tests and nothing failed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With