c++ - 如何解释 is_assignable 中的 declval<_Dest>() = declval<_Src>()

标签 c++ c++11

我想弄清楚如何在 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 的情况?

谢谢。

最佳答案

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&& 可以从任何 类型赋值,那么它就有一个错误。 §5.17 [expr.ass] p1 声明:

The assignment operator (=) and the compound assignment operators all group right-to-left. All require a modifiable lvalue as their left operand and return an lvalue referring to the left operand.

[强调我的]。

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

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

关于c++ - 如何解释 is_assignable 中的 declval<_Dest>() = declval<_Src>(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20414883/

相关文章:

c++ - 是否可以在容器中放置 std::array?如果是怎么样?如果不是,为什么?

c++ - 更改 GNU 编译器中的 -g 标志使 c++ 可执行

C++ Qt QtConcurrent::filteredReduced 从 std::shared_ptr 的 QVector

c++ - Windows 时间限制应用程序能否在时间到时将游戏退出全屏(DirectX?)模式?

没有模板参数的 C++ 模板?

c++ - 禁用 move 构造函数

c++ - 从控制台获取多个字符串并将它们写为 C++ 中的列表

c++ - 为什么这个程序被三个 C++ 编译器错误地拒绝了?

c++ - CMake 为 C 文件禁用 -std=c++11 标志

c++ - 错误 "C++ requires a type specifier for all declarations"