具有引用的std :: tuple无法在clang中编译,但在gcc中无法编译

以下代码:

using input_t = std::tuple<short,int&,const long&,const double>;
int b = 1;
int c = 2;
input_t t{0,b,c,3};

将无法在clang 9.0中编译,但会以gcc 9.2成功:https://godbolt.org/z/6CuEaf

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 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 &,void>' requested here

/tuple:627:11: note: in instantiation of function template specialization 'std::_Tuple_impl<0,short,const double>::_Tuple_impl<int,void>' requested here

    : _Inherited(std::forward<_UElements>(__elements)...) { }

      ^

<source>:10:13: note: in instantiation of function template specialization 'std::tuple<short,const double>::tuple<int,true>' requested here

input_t t{0,3};

        ^

下面哪个是正确的?我看不到会导致超过bc生存期的任何事情。


quzhuanglin 回答:具有引用的std :: tuple无法在clang中编译,但在gcc中无法编译

考虑以下代码:

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;
}   

其输出如下:

constructed from 1
0x7fff6a0bb78b
destructed
0x7fff6a0bb78b

实时演示为here

在这里,类似物std::tupleY相似。在Y y(i)中,参数ref绑定到类型为X的临时变量。但是,随着ref参数的生存期结束,此临时文件被破坏。然后,{@ {1}}变成了悬空的引用,就像@ rafix07在评论中指出的那样。

因此,以导致绑定到临时表的方式初始化引用类型的元组成员是没有意义的。问题是,是否需要编译器在此处发出诊断信息。我认为不是必须的,并且在[tuple]中看不到任何相关信息。

关于ref_,它只是说:

  

forward_as_tuple中构造对参数的引用的元组,适合作为参数传递给函数。 由于结果可能包含对临时对象的引用,因此程序应确保该函数的返回值不会超过其任何参数

但是t(“直接”)构造函数的定义没有相同的措辞。

本文链接:https://www.f2er.com/3123540.html

大家都在问