简体   繁体   English

带引用的 std::tuple 在 clang 中编译失败,但在 gcc 中编译失败

[英]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 .我没有看到任何应该导致超过bc的寿命的东西。


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

Live demo is here .现场演示在这里

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM