【问题标题】:libc++ vs libstdc++ std::is_move_assignable: Which is the most correct?libc++ vs libstdc++ std::is_move_assignable:哪个最正确?
【发布时间】:2016-10-11 20:29:35
【问题描述】:

我试图通过阅读 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> {};

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&lt;T&amp;, T&amp;&amp;&gt;::value 相同,否则为false

我注意到的第一件事是 libc++ 将const 应用于第二个模板参数,这似乎不正确,因为移动赋值运算符采用非常量右值。 libstdc++ 也使用__is_referenceable,它遵循标准的措辞,但 libc++ 没有。 libc++ 对add_lvalue_referenceadd_rvalue_reference 的使用是否涵盖了这一要求,它们都自行强制执行__is_referenceable

如果能深入了解每个项目为何选择他们的解决方案,我将不胜感激!

【问题讨论】:

  • 对于任何可引用的东西,const 是没有意义的(当应用于引用类型时,cv 限定符被忽略)。
  • @T.C.谢谢!知道为什么作者可能会添加const吗?
  • 很少有这样的响应时间:github.com/llvm-mirror/libcxx/commit/… :-)

标签: c++ c++11 c++14 libstdc++ libc++


【解决方案1】:

谢谢!知道为什么作者可能会添加const吗?

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

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

;-)

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

【讨论】:

    【解决方案2】:

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

    (从差异来看,这对我来说确实像是暂时的精神错乱:)似乎是 is_copy_assignable 的(错误)实现导致的 C&P 问题。)

    对于任何不可引用的内容(即 cv void 或可恶的函数类型),libstdc++ 返回 false_type

    在 libc++ 中,add_{l,r}value_reference 将其原封不动地返回(这取决于 C++14 之后的问题解决方案)。在顶部洒上 const 对 AFT 没有任何作用,并为 voidy 类型添加 const

    然后我们转到is_assignable,SFINAE 测试declval&lt;T&gt;() = declval&lt;U&gt;() 的良构性,用于T == U == some AFTT == some void typeU = some const-qualified void type。在所有情况下,表达式都是格式错误的(以 SFINAE 友好的方式),所以我们得到了false_type

    两者是等价的。

    【讨论】:

      【解决方案3】:

      __is_referenceable 是一个非标准的内部 libstdc++ 例程。 (这并不意味着它不好,只是我不希望 libc++ 使用它)。此外,“可参考”概念的出现要晚于is_move_assignable

      __is_referenceable 有助于处理“可恶的功能”; int (*) (double) &amp;&amp; 之类的东西。

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

      【讨论】:

      • libc++ 实际上确实为 add_lvalue_referenceadd_rvalue_reference 的实现定义了 __is_referenceable,但我不确定是否通过使用 add_rvalue_reference 来“隐式”应用 __is_referenceable产生与 libstdc++ 显式使用 __is_referenceable 相同的行为。对不起,如果这没有意义。
      • (*) 不应该在那里 :)
      猜你喜欢
      • 2018-12-20
      • 2018-05-10
      • 2017-01-03
      • 1970-01-01
      • 1970-01-01
      • 2022-01-07
      • 1970-01-01
      • 2017-02-22
      • 1970-01-01
      相关资源
      最近更新 更多