在下面的代码中,我不允许声明显式 ctor,因为编译器说我在 copy-initializing 上下文中使用它(clang 3.3和gcc 4.8 )。 我试图通过使ctor非显式,然后将复制构造函数声明为已删除来证明编译器是错误的。
编译器是错误还是有其他解释?
#include <iostream>
template <typename T>
struct xyz
{
constexpr xyz (xyz const &) = delete;
constexpr xyz (xyz &&) = delete;
xyz & operator = (xyz const &) = delete;
xyz & operator = (xyz &&) = delete;
T i;
/*explicit*/ constexpr xyz (T i): i(i) { }
};
template <typename T>
xyz<T> make_xyz (T && i)
{
return {std::forward<T>(i)};
}
int main ()
{
//auto && x = make_xyz(7);
auto && x (make_xyz(7)); // compiler sees copy-initialization here too
std::cout << x.i << std::endl;
}
更新一个不切实际但更简单的版本
struct xyz {
constexpr xyz (xyz const &) = delete;
constexpr xyz (xyz &&) = delete;
xyz & operator = (xyz const &) = delete;
xyz & operator = (xyz &&) = delete;
int i;
explicit constexpr xyz (int i): i(i) { }
};
xyz make_xyz (int && i) {
return {i};
}
int main () {
xyz && x = make_xyz(7);
}
答案 0 :(得分:7)
=
表示法不应影响投诉,因为无论是直接初始化还是复制初始化,引用绑定的行为都不同。这里初始化的是返回值对象,它没有自己的名称。
不幸的是,GCC和Clang一样抱怨是对的。根据§6.6.3/ 2 [stmt.return],
带有braced-init-list的return语句初始化要从指定的初始化列表中通过copy-list-initialization(8.5.4)从函数返回的对象或引用。
所以,那里有一个看不见的=
符号,你无法绕过它。