7

在下面的代码中,我不允许声明显式ctor,因为编译器说我在复制初始化上下文(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); 
}
4

1 回答 1

7

=符号不应影响投诉,因为无论是通过直接初始化还是复制初始化,引用绑定的行为都不会有所不同。这里初始化的是返回值对象,它没有自己的名字。

不幸的是,GCC 的抱怨是正确的,Clang 也是如此。根据§6.6.3/2 [stmt.return],

带有花括号初始化列表的 return 语句通过指定初始化列表中的复制列表初始化 (8.5.4) 初始化要从函数返回的对象或引用。

所以,那里有一个看不见的=标志,你无法绕过它。

于 2013-12-13T05:28:50.560 回答