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

How to interpret declval<_Dest>() = declval<_Src>() in is_assignable

本文关键字:lt gt declval Src is Dest 解释 assignable      更新时间:2023-10-16

我正试图弄清楚如何解释declval&lt_Dest>()=递减&lt_Src>()在is_assignable的实现中。

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

  1. _Dest&amp;=_Src&amp
  2. _Dest&amp;=_Src&
  3. _目的地&=_Src&amp
  4. _目的地&=_Src&

然后我创建了两个辅助函数。

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

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

  1. _Dest&amp;=_Src&amp;----->右值&lt_Dest>()=右值&lt_Src>()

其他三个也是如此。

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

  • _Dest=int,_Src=int。编译器接受#3和#4。is_assignable为#3和#4返回true。他们同意了
  • _Dest=int,_Src=double。与相同的结果
  • _Dest=double,_Src=int。对于这一点,编译器和is_assignable并不一致。编译器再次不喜欢为右值赋值。但是,对于所有四种可能性,is_assignable都返回true

我的问题是

  • 我把declval&lt_Dest>()=递减&lt_Src>()是否正确?换句话说,这真的可以转化为四种可能性吗。如果是,每一个都可以映射到模板化的函数表达式吗
  • 为什么编译器和is_assignable在_Dest=double、_Src=int的情况下存在分歧

谢谢。

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

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

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

如果编译器认为double&&可以从任何类型赋值,那么它就有一个错误。§5.17【expr.ass】p1规定:

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

[强调我的]。

许多程序员选择用自己的类型来模拟这种行为——只对左值进行分类——通过用左值引用限定符声明赋值运算符:

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