支撑初始化与括号错误

ale*_*cov 9 c++ gcc c++11 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); }
Run Code Online (Sandbox Code Playgroud)

和:

#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); }
Run Code Online (Sandbox Code Playgroud)

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

这是GCC的错误吗?还是这的确之间的差异T{},并T()在上述背景下(因此臭虫锵和MSVC)?

编辑:

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

int i; (int&){i};
Run Code Online (Sandbox Code Playgroud)

int i; (int&)(i);
Run Code Online (Sandbox Code Playgroud)

T.C*_*.C. 6

有两个不同的问题:

  • 该标准尚不清楚T{x}应该如何为参考类型做T.目前[expr.type.conv]/1表示它创建了一个类型的prvalue T,这对于引用类型来说是无意义的.这是核心问题1521.
  • 理智的事情可能是T{x}为了引用类型T粗略地做T __tmp{x};,然后产生等价的static_cast<T>(__tmp)(所以对于右值引用的xvalue T和对于左值引用的左值T).但是,发布的C++ 11搞砸了引用列表初始化的规范,使它始终创建一个临时的.结果是int i; int &r{i};编译失败,因为它会尝试绑定r到临时副本i,这显然是无稽之谈.这是由核心问题1288修复的,其解析GCC应该实现,但从错误消息看起来它并没有完全修复.