[英]Initializing lvalue reference with rvalue
I built this code with gcc/clang and got different results: 我用gcc / clang构建了此代码,并得到了不同的结果:
#include <iostream>
#include <sstream>
int main() {
std::istream& is = 1 ? std::move(std::stringstream("")) : std::cin;
}
std::stringstream("")
)? std::stringstream("")
)初始化左值引用? No error 没错
prog.cc:5:63: error: call to implicitly-deleted copy constructor of 'istream' (aka 'basic_istream<char>')
std::istream& is = 1 ? std::move(std::stringstream("")) : std::cin;
^~~~~~~~
/usr/local/libcxx-3.4/include/c++/v1/istream:185:5: note: copy constructor is implicitly deleted because 'basic_istream<char, std::__1::char_traits<char> >' has a user-declared move constructor
basic_istream(basic_istream&& __rhs);
^
prog.cc:5:28: error: calling a protected constructor of class 'std::__1::basic_istream<char, std::__1::char_traits<char> >'
std::istream& is = 1 ? std::move(std::stringstream("")) : std::cin;
^
/usr/local/libcxx-3.4/include/c++/v1/istream:185:5: note: declared protected here
basic_istream(basic_istream&& __rhs);
^
prog.cc:5:28: error: calling a protected constructor of class 'std::__1::basic_istream<char, std::__1::char_traits<char> >'
std::istream& is = 1 ? std::move(std::stringstream("")) : std::cin;
^
/usr/local/libcxx-3.4/include/c++/v1/istream:185:5: note: declared protected here
basic_istream(basic_istream&& __rhs);
^
GCC's behavior is a bug, and it's been fixed on trunk . GCC的行为是一个错误,并且已在trunk上修复 。 Clang is correct.
lang是正确的。 This is a messy case because you have mixed value categories for the second and third operands of the conditional operator:
这是一个混乱的情况,因为您为条件运算符的第二和第三操作数混合了值类别:
std::move(std::stringstream(""))
is an xvalue * of type std::stringstream
; std::move(std::stringstream(""))
是类型为std::stringstream
的xvalue * ; std::cin
is an lvalue of type std::istream
. std::cin
是std::istream
类型的左值。 The relevant standard quote (§5.16 [expr.cond]/p3-6) can be found in this answer . 相关标准报价(§5.16[expr.cond] / p3-6)可以在此答案中找到。 It's long enough that I don't really want to copy it over.
足够长的时间,我真的不想复制它。 I'll just outline how it is applied to this code:
我将概述它如何应用于此代码:
std::istream
cannot be converted to match std::stringstream
in any way regardless of value category; std::istream
转换为与std::stringstream
匹配; std::stringstream
cannot be converted to type "lvalue reference to std::istream
" given the constraint that the reference must bind directly to an lvalue - there's no lvalue here for the reference to bind to; std::stringstream
的xvalue转换为“对std::istream
lvalue引用”类型-这里没有lvalue可供引用绑定; std::istream
is a base class of std::stringstream
, so per the 3rd bullet of p3, the xvalue of type std::stringstream
can and will be converted to a prvalue temporary of type std::istream
by copy-initialization, which replaces the original operand for further analysis. std::istream
是std::stringstream
的基类,因此根据p3的第3个项目符号,可以并且通过复制初始化将类型std::stringstream
的xvalue转换为类型为std::istream
的prvalue临时对象,它将替换原始操作数以进行进一步分析。 std::istream
, the third operand is an lvalue of type std::istream
, they have different value categories so p4 doesn't apply. std::istream
类型的prvalue,第三个操作数是std::istream
类型的lvalue,它们具有不同的值类别,因此p4不适用。 The applicable bullet in p6 is 第6页中的适用项目符号为
The second and third operands have the same type;
第二和第三操作数具有相同的类型。 the result is of that type.
结果就是这种类型。 If the operands have class type, the result is a prvalue temporary of the result type, which is copy-initialized from either the second operand or the third operand depending on the value of the first operand.
如果操作数具有类类型,则结果是该结果类型的prvalue临时值,它会根据第一个操作数的值从第二个操作数或第三个操作数进行复制初始化。
so it copy-initializes the result (which is a prvalue temporary) from either the converted first operand, or the second operand ( std::cin
). 因此它从转换后的第一个操作数或第二个操作数(
std::cin
)复制结果(这是一个prvalue临时值)。
Hence the errors: 因此错误:
std::istream
result from an lvalue ( std::cin
) would use the copy constructor, and streams cannot be copied. std::cin
)复制初始化prvalue std::istream
结果将使用复制构造函数,并且无法复制流。 std::istream
for the second operand from a std::stringstream
xvalue is a move, but std::istream
's move constructor is protected. std::stringstream
xvalue复制第二个操作数的prvalue临时std::istream
是移动,但std::istream
的move构造函数受到保护。 * For terminology (lvalue, xvalue, prvalue, etc.), see What are rvalues, lvalues, xvalues, glvalues, and prvalues? *有关术语(lvalue,xvalue,prvalue等),请参阅什么是rvalue,lvalue,xvalues,glvalues和prvalue?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.