如何在is_assignable中解释declval< _Dest>()= declval< _Src>()

时间:2013-12-06 02:35:23

标签: c++ c++11

我试图弄清楚如何在is_assignable的实现中解释declval< _Dest>()= declval< _Src>()。

declval将类型转换为引用。鉴于此,我将表达式转换为以下四种可能性之一:

  1. _dest&安培;&安培; = _Src&&
  2. _dest&安培;&安培; = _Src&
  3. _dest&安培; = _Src&&
  4. _dest&安培; = _Src&
  5. 然后我创建了两个辅助函数。

    template <typename T> T rvalue();
    template <typename T> T& lvalue();
    

    我的理解是可以使用模板函数实现四个表达式。

    1. _dest&安培;&安培; = _Src&amp;&amp; -----&GT; rvalue&lt; _Dest&gt;()= rvalue&lt; _Src&gt;()
    2. 其他三个也一样。

      然后我通过编译三对具体类型的每种可能性的模板化函数版本来模拟decltype(declval&lt; _Dest&gt;()= declval&lt; _Src&gt;(),..)。

      • _Dest = int,_Src = int。编译器接受#3和#4。对于#3和#4,is_assignable返回true。他们同意了。
      • _Dest = int,_Src = double。与
      • 相同的结果
      • _Dest = double,_Src = int。对于这个,编译器和is_assignable不同意。编译器再次不喜欢分配给rvalues。但是,对于所有四种可能性,is_assignable都返回true。

      我的问题是

      • 我是否正确解释了declval&lt; _Dest&gt;()= declval&lt; _Src&gt;()?换句话说,这是否真正转化为四种可能性。如果是,可以将每个映射到模板化函数表达式吗?
      • 为什么编译器和is_assignable在_Dest = double,_Src = int情况下不一致?

      感谢。

1 个答案:

答案 0 :(得分:3)

std::declval实际上被指定为(C ++11§20.2.4[declval] p1):

template <class T>
typename add_rvalue_reference<T>::type declval() noexcept;

引用折叠规则(第8.3.2节[dcl.ref] p6)的结果是declvalT是左值引用类型时返回左值引用,否则返回右值引用。是的,你的解释是正确的。

如果您的编译器认为double&&可以从任何类型分配,那么它就有一个错误。 §5.17[expr.ass] p1陈述:

  

赋值运算符(=)和复合赋值运算符从右到左分组。所有都需要可修改的左值作为左操作数,并返回左值操作数的左值。

[强调我的]。

许多程序员选择通过使用左值引用限定符声明赋值运算符来模拟此行为 - 仅限于左值 - 使用自己的类型:

class foo {
  foo& operator = (const foo&) & = default;
  foo& operator = (foo&&) & = default;
};