大括号初始化与括号错误
Brace-initialization vs. Parenthesis Bug
我为此提交了一个 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);
有两个不同的问题:
- 标准不清楚
T{x}
应该为引用类型 T
做什么。目前 [expr.type.conv]/1 says that it creates a prvalue of type T
, which is nonsense for reference types. This is core issue 1521.
- 理智的事情可能是让
T{x}
对于引用类型 T
大致做 T __tmp{x};
然后产生等价于 static_cast<T>(__tmp)
(所以右值引用的 xvalue T
和左值引用的左值 T
)。然而,发布的 C++11 搞砸了引用列表初始化的规范,使其总是创建一个临时的。结果是 int i; int &r{i};
编译失败,因为它会尝试将 r
绑定到 i
的临时副本,这显然是无稽之谈。这是由 core issue 1288 修复的,它的分辨率 GCC 应该实现,但从错误消息来看它似乎没有完全修复。
我为此提交了一个 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);
有两个不同的问题:
- 标准不清楚
T{x}
应该为引用类型T
做什么。目前 [expr.type.conv]/1 says that it creates a prvalue of typeT
, which is nonsense for reference types. This is core issue 1521. - 理智的事情可能是让
T{x}
对于引用类型T
大致做T __tmp{x};
然后产生等价于static_cast<T>(__tmp)
(所以右值引用的 xvalueT
和左值引用的左值T
)。然而,发布的 C++11 搞砸了引用列表初始化的规范,使其总是创建一个临时的。结果是int i; int &r{i};
编译失败,因为它会尝试将r
绑定到i
的临时副本,这显然是无稽之谈。这是由 core issue 1288 修复的,它的分辨率 GCC 应该实现,但从错误消息来看它似乎没有完全修复。