【发布时间】:2019-11-11 14:21:18
【问题描述】:
以下代码:
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 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};
^
这里哪一个是正确的?我没有看到任何应该导致超过 b 和 c 的生命周期的东西。
【问题讨论】:
-
你想如何将
int绑定到long?临时实例是通过将int提升为long创建的,然后这个temp 绑定到const long&。你有悬空的参考。将这一行添加到代码中:std::cout << &c << std::endl;和std::cout << &std::get<2>(t) << std::endl;您将看到两个不同的地址,但两者应该相同。当c很长时,这些地址将具有相同的值。 -
@rafix07 啊啊啊啊!完美的。那么GCC在这里错了吗?我想是的。
-
@rafix07 完全正确,但它并没有告诉您编译器是否应该在编译时拒绝代码。只要不直接使用
std::get<2>(t),就没有UB。
标签: c++ g++ language-lawyer clang++