我试图通过阅读C++标准以及libc++和libstdc++的源代码来更深入地理解C++14。不同的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> {};
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>
{ };
该标准规定:
对于可引用类型T
,返回
,结果与
is_assignable<T&, T&&>::value
相同,否则返回false
。
我注意到的第一件事是,libc++将const
应用于第二个模板参数,这似乎不正确,因为移动赋值操作符采用非常量值。libstdc++也使用了__is_referenceable
,它遵循了标准的措辞,但是libc++没有,这是不是已经被libc++使用的add_lvalue_reference
和add_rvalue_reference
所覆盖了,这两个语言都是自己执行__is_referenceable
的?
如果您能深入了解每个项目选择解决方案的原因,我将不胜感激!
发布于 2016-10-12 05:49:57
对于任何可引用的东西,这两个实现都做了同样的事情,因为libc++中的无关const
是没有意义的,但也是无害的。
(从差异来看,在我看来肯定是暂时的疯狂:)似乎是一个(错误的)is_copy_assignable
实现造成的C&P问题。)
对于任何不可引用的类型(例如,cv void
或可恶的函数类型),libstdc++返回false_type
。
在libc++中,add_{l,r}value_reference
原封不动地返回它(这取决于C++14之后的问题解决方案)。在顶部散布const
不会对AFT产生任何影响,而会为void
y类型添加一个const
。
然后我们转到is_assignable
,它为T == U == some AFT
或T == some void type
和U = some const-qualified void type
测试declval<T>() = declval<U>()
的良好性。在所有情况下,表达式都是病态的(以一种对SFINAE友好的方式),因此我们得到了false_type
。
这两个是等价的。
发布于 2016-10-12 05:06:21
,谢谢!那么,你知道作者为什么要添加
const
吗?
我最好的猜测是暂时的(希望)精神错乱:
;-)
我删除了const
并运行了当前的单元测试,没有任何失败。
发布于 2016-10-12 05:16:43
__is_referenceable
是一个非标准的内部libstdc++例程。(这并不意味着它不好,只是我不期望libc++使用它)。此外,“可引用”的概念比is_move_assignable
出现得晚得多。
在处理像int (*) (double) &&
这样的“令人讨厌的函数”时,__is_referenceable
是有帮助的。
看起来我需要写更多的测试:-)
https://stackoverflow.com/questions/39986185
复制相似问题