[英]std::tuple with reference fails to compile in clang, but not in gcc
The following code:以下代码:
using input_t = std::tuple<short, int&, const long&, const double>;
int b = 1;
int c = 2;
input_t t{0, b, c, 3};
Will fail to compile in clang 9.0
but succeeds with gcc 9.2
: https://godbolt.org/z/6CuEaf将无法在
clang 9.0
中编译,但在gcc 9.2
中编译成功: https://godbolt.org/z/6CuEaf
clang
will fail with the error: clang
将失败并出现以下错误:
In file included from <source>:2:
tuple:133:17: error: reference member '_M_head_impl' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object
: _M_head_impl(std::forward<_UHead>(__h)) { }
^~~~~~~~~~~~~~~~~~~~~~~~~
/tuple:218:4: note: in instantiation of function template specialization 'std::_Head_base<2, const long &, false>::_Head_base<int &>' requested here
_Base(std::forward<_UHead>(__head)) { }
^
/tuple:217:4: note: in instantiation of function template specialization 'std::_Tuple_impl<2, const long &, const double>::_Tuple_impl<int &, int, void>' requested here
: _Inherited(std::forward<_UTail>(__tail)...),
^
/tuple:217:4: note: in instantiation of function template specialization 'std::_Tuple_impl<1, int &, const long &, const double>::_Tuple_impl<int &, int &, int, void>' requested here
/tuple:627:11: note: in instantiation of function template specialization 'std::_Tuple_impl<0, short, int &, const long &, const double>::_Tuple_impl<int, int &, int &, int, void>' requested here
: _Inherited(std::forward<_UElements>(__elements)...) { }
^
<source>:10:13: note: in instantiation of function template specialization 'std::tuple<short, int &, const long &, const double>::tuple<int, int &, int &, int, true>' requested here
input_t t{0, b, c, 3};
^
Which one is correct here?这里哪一个是正确的? I don't see anything that should result in exceeding the lifetime of
b
and c
.我没有看到任何应该导致超过
b
和c
的寿命的东西。
Consider the following code:考虑以下代码:
struct X
{
X(int i)
{
std::cerr << "constructed from " << i << std::endl;
}
~X() { std::cerr << "destructed\n"; }
};
struct Y
{
const X& ref_;
Y(const X& ref) : ref_(ref)
{
std::cerr << &ref << std::endl;
}
};
int main ()
{
int i = 1;
Y y(i);
std::cerr << &y.ref_ << std::endl;
}
Its output is as follows:其output如下:
constructed from 1
0x7fff6a0bb78b
destructed
0x7fff6a0bb78b
It kind-of simulates std::tuple
with Y
here.它在这里用
Y
模拟std::tuple
。 In Y y(i)
, a parameter ref
is bound to a temporary of type X
.在
Y y(i)
中,参数ref
绑定到X
类型的临时变量。 But this temporary is destructed as the lifetime of ref
parameter is ended.但是随着
ref
参数的生命周期结束,这个临时的被破坏了。 Then, ref_
becomes a dangling reference, as @rafix07 pointed out in a comment.然后,正如@rafix07 在评论中指出的那样,
ref_
成为一个悬空引用。
It therefore makes no sense to initialize a tuple member of a reference type in such a way that results in a binding to a temporary.因此,以导致绑定到临时对象的方式初始化引用类型的元组成员是没有意义的。 The question is whether a compiler is required to issue a diagnostic here.
问题是编译器是否需要在这里发出诊断。 I don't think it has to and I don't see any relevant information in [tuple] .
我认为没有必要,而且我在[tuple]中看不到任何相关信息。
It just says, regarding forward_as_tuple
:它只是说,关于
forward_as_tuple
:
Constructs a tuple of references to the arguments in
t
suitable for forwarding as arguments to a function.在
t
中构造对 arguments 的引用元组,适合作为 arguments 转发到 function。 Because the result may contain references to temporary objects, a program shall ensure that the return value of this function does not outlive any of its arguments .因为结果可能包含对临时对象的引用,所以程序应确保此 function 的返回值不会超过它的任何 arguments 。
But the same wording is not present by the definition of tuple
("direct") constructor.但是
tuple
(“直接”)构造函数的定义不存在相同的措辞。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.