我想弄清楚如何在 is_assignable 的实现中解释 declval<_Dest>() = declval<_Src>()。
declval 将类型转换为引用。鉴于此,我将表达式转换为以下四种可能性之一:
- _Dest&& = _Src&&
- _Dest&& = _Src&
- _Dest& = _Src&&
- _Dest& = _Src&
然后我创建了两个辅助函数。
template <typename T> T rvalue();
template <typename T> T& lvalue();
我的理解是这四个表达式可以用模板函数实现。
- _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/