支撑初始化与括号错误

时间:2016-10-03 20:45:03

标签: c++ c++11 gcc list-initialization

我正在为此提交GCC错误,但我宁愿再仔细检查一下。

考虑以下计划:

#include <utility>
template<typename T, typename A>
void F(A&& a) { T(std::forward<A>(a)); } // Note: () syntax.
int main() { int i; F<int&>(i); }

#include <utility>
template<typename T, typename A>
void F(A&& a) { T{std::forward<A>(a)}; } // Note: {} syntax.
int main() { int i; F<int&>(i); }

最新的Clang和MSVC编译器都接受这两个程序。 GCC 5及更高版本接受第一个程序但拒绝第二个程序,声称invalid cast of an rvalue expression of type 'int' to type 'int&'

这是GCC的错误吗?或者在上面的上下文中这确实是T{}T()之间的差异(因此Clang和MSVC中的错误)?

修改

问题可以缩小到以下简单的摘录:

int i; (int&){i};

int i; (int&)(i);

1 个答案:

答案 0 :(得分:6)

有两个不同的问题:

  • 标准不清楚T{x}应该为引用类型T做什么。目前[expr.type.conv]/1表示它会创建类型为T的prvalue,这对于引用类型来说是无意义的。这是core issue 1521
  • 理智的事情可能是T{x}引用类型T大致T __tmp{x};然后产生相当于static_cast<T>(__tmp)(因此对于右值引用{{1}的xvalue左值引用T)的左值和左值。但是,发布的C ++ 11搞砸了引用列表初始化的规范,使它始终创建一个临时的。结果是T无法编译,因为它会尝试将int i; int &r{i};绑定到r的临时副本,这显然是无意义的。这由core issue 1288修正,其解析GCC应该实现,但从错误消息看起来它并没有完全修复。