我为此提交了一个 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 及更高版本接受第一个程序但拒绝第二个程序,声称 将类型为“int”的右值表达式无效转换为类型为“int&”
。
这是 GCC 错误吗?或者这确实是上述上下文中 T{}
和 T()
之间的区别(因此是 Clang 和 MSVC 中的错误)?
编辑:
问题可以缩小为以下更简单的摘录:
int i; (int&){i};
和
int i; (int&)(i);
最佳答案
有两个不同的问题:
- 不清楚标准是什么
T{x}
应该做引用类型T
.目前[expr.type.conv]/1说它创建了一个类型为T
的纯右值,这对引用类型来说是无稽之谈。这是 core issue 1521 . - 理智的事情可能是
T{x}
供引用类型T
大致做T __tmp{x};
然后产生相当于static_cast<T>(__tmp)
(因此右值引用的 xvalueT
和左值引用的 lvalueT
)。然而,发布的 C++11 搞砸了引用列表初始化的规范,使其总是创建一个临时的。结果是int i; int &r{i};
编译失败,因为它会尝试绑定(bind)r
到i
的临时拷贝,这显然是无稽之谈。这是由 core issue 1288 修复的, 其分辨率 GCC 应该实现,但从错误消息中看似乎没有完全修复。
关于c++ - 大括号初始化与括号错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39840117/