libc ++ vs libstdc ++ std :: is_move_assignable:哪个最正确?

Dav*_*own 17 c++ libstdc++ c++11 libc++ c++14

我正在尝试通过阅读C++ 14标准以及libc ++和libstdc ++的源代码来更深入地理解C++.type_traits两者之间的各种项目的实施情况各不相同,特别是is_move_assignable,我试图弄清楚哪些项目"更正确".

的libc ++:

template <class _Tp> struct is_move_assignable
    : public is_assignable<typename add_lvalue_reference<_Tp>::type,
                           const typename add_rvalue_reference<_Tp>::type> {};
Run Code Online (Sandbox Code Playgroud)

的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>
  { };
Run Code Online (Sandbox Code Playgroud)

标准规定:

对于可引用类型T,结果与is_assignable<T&, T&&>::value否则相同false.

我注意到的第一件事是libc ++适用const于第二个模板参数,这似乎不正确,因为移动赋值运算符采用非const rvalue.libstdc ++也使用__is_referenceable,遵循标准的措辞,但libc ++没有.是通过规定的libc ++的使用覆盖add_lvalue_referenceadd_rvalue_reference,这既加强__is_referenceable自己?

我真的很感激为什么每个项目都选择他们的解决方案!

How*_*ant 8

谢谢!知道作者为什么会添加const,然后呢?

我最好的猜测是暂时的(希望)精神错乱:

https://github.com/llvm-mirror/libcxx/commit/6063ec176d5056683d6ddd310c2e3a8f1c7e1b46#diff-48f5ee43879b5ad38888f0a6ead10113R1245

;-)

我删除了const并运行了当前的单元测试,没有任何失败.


T.C*_*.C. 6

对于任何可引用的东西,这两个实现都做同样的事情,因为constlibc ++中的无关是没有意义的,但也是无害的.

(从差异来看,它对我来说当然看起来像是暂时的疯狂:)似乎是(错误的)实施的C&P问题is_copy_assignable.)

对于任何不可引用的东西(即cv void或abominable函数类型),libstdc ++都会返回false_type.

在libc ++中,add_{l,r}value_reference返回它不变(这取决于后期C++ 14的问题解决方案).洒const在顶部对AFT没有任何作用,并constvoidy类型添加了一个.

然后,我们去is_assignable,这SFINAE检验的良好性declval<T>() = declval<U>(),对于任何一个T == U == some AFTT == some void typeU = some const-qualified void type.在所有情况下,表达形式都不正确(以SFINAE友好的方式),所以我们false_type回来了.

两者是等价的.


Mar*_*low 5

__is_referenceable是一个非标准的内部libstdc ++例程.(这并不意味着它很糟糕,只是我不希望libc ++使用它).此外,"可参考"概念出现的时间要晚得多is_move_assignable.

__is_referenceable处理"可恶的功能"时的帮助; 比如int (*) (double) &&.

看起来我需要写更多测试:-)