我正在为此提交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);
答案 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应该实现,但从错误消息看起来它并没有完全修复。