【问题标题】:How to interpret declval<_Dest>() = declval<_Src>() in is_assignable如何在 is_assignable 中解释 declval<_Dest>() = declval<_Src>()
【发布时间】:2013-12-06 02:35:23
【问题描述】:

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

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

  1. _Dest&& = _Src&&
  2. _Dest&& = _Src&
  3. _Dest& = _Src&&
  4. _Dest& = _Src&

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

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

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

  1. _Dest&& = _Src&& -----> 右值<_dest>() = 右值<_src>()

其他三个也一样。

然后我通过编译三对具体类型的每种可能性的模板函数版本来模拟 decltype(declval<_dest>() = declval<_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<_dest>() = declval<_src>()?换句话说,这是否真的转化为四种可能性。如果是,是否可以将每个都映射到模板化函数表达式?
  • 为什么编译器和 is_assignable 在 _Dest=double, _Src=int 情况下存在分歧?

谢谢。

【问题讨论】:

  • 哪个编译器是“那个”编译器?至少一个编译器似乎可以工作precisely as you expect
  • 编译器为VC++2013

标签: c++ c++11


【解决方案1】:

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) 的结果是,当 T 是左值引用类型时,declval 返回左值引用,否则返回右值引用。所以是的,你的解释是正确的。

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

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

[强调我的]。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-06-02
    • 1970-01-01
    • 1970-01-01
    • 2019-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多