【问题标题】:This is not copy-initializing, or is it?这不是复制初始化,是吗?
【发布时间】:2013-12-31 19:33:03
【问题描述】:

在下面的代码中,我不允许声明 explicit 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); 
}

【问题讨论】:

    标签: c++ c++11 explicit-constructor copy-initialization


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 真可惜!首先,他们告诉我们要干净并在有意义的地方使用 explicit。然后当我们做 8-(.
    • @PatrickFromberg TBH 我不确定 explicit 在哪里有意义,除了 C++03 的情况,或者多参数调用可能与 std::initializer_list 重载不明确。但是对于没有参数,默认构造函数的优先级特别高于std::initializer_listexplicit 的名义效果是强制你命名类而不是让它是隐式的,所以在这种情况下它完成了它的工作:P。
    • 关于“强制你命名类”。在初始化列表和命名结果类型之间实际上没有副本。我在我的问题中添加了一个更简单的示例以确保。毕竟 copy-initializerexplicit 不兼容的最终原因是为了防止模糊的转换。但我在这里没有看到模糊的转换。不幸的是,正如您正确引用的那样,该标准根据定义说这是复制初始化,您不能反对定义。
    • @PatrickFromberg 术语 copy-list-initialization 不是指复制构造函数,而只是等同于 = 符号的用法。它不是“复制初始化”,而是具体的 copy-list-initialization,它是一个不可分割的、名称有些混淆的概念。
    • 等同于使用 = 符号”并不能真正减少混淆。但这不是你的错,我在C++ Bible 也看到了这个描述。但我确实错过了 copy-initializationcopy-list-initialization 之间的区别。很好,你指出了这一点。
    猜你喜欢
    • 1970-01-01
    • 2023-03-09
    • 1970-01-01
    • 2021-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多