【问题标题】:Constructing a non-copyable, non-movable type into a function parameter without invoking initializer_list constructor在不调用 initializer_list 构造函数的情况下将不可复制、不可移动的类型构造为函数参数
【发布时间】:2014-05-02 12:58:36
【问题描述】:
#include <initializer_list>
#include <iostream>

namespace {

class C {
public:
    C(C const &) = delete;
    C(C &&) = delete;
    C(int) {
        std::cout << "int\n";
    }
    C(std::initializer_list<int>) {
        std::cout << "initializer\n";
    }
};

void f(C) {
}

// Compiles and prints "initializer" when called
C g() { return {0}; }
// Fails to compile
// C h() { return 0; }

}   // namespace

int main() {
    // Compiles and prints "initializer"
    f({0});
    // Fails to compile
    // f(0);
}

是否可以在不调用initializer_list构造函数的情况下将C这个不可复制、不可移动的类型构造成函数参数或函数返回值?

【问题讨论】:

  • 我看不到这样做的方法(这也是类内初始化程序的问题:struct A { std::vector&lt;int&gt; x{2}; }。您无法将 x 初始化为具有 2 的大小。并且不能说= 2,因为构造函数是显式的)。
  • 您正在传递不可复制等类型的对象的副本。为什么?没有意义
  • @deviantfan:我正在尝试直接在原地构造对象。
  • @JohannesSchaub-litb,你不能说struct A { vector&lt;int&gt; x = vector&lt;int&gt;(2); };吗?我现在无法测试它,因为 GCC 4.6 不支持类内初始化程序。
  • @DavidStone,我不相信你可以。如果initializer_list 构造函数在大括号初始化中匹配,它优先于非initializer_list 构造函数,我想不出一种方法使大括号初始值设定项匹配int 构造函数,而不是initializer_list .我能想到的所有其他构造 C 的方法在传递给函数或从函数返回时都会涉及(名义)临时,这与不可复制、不可移动的类不兼容。

标签: c++ c++11 initializer-list


【解决方案1】:

只有当您可以更改 C 时才有可能选择所需的构造函数而不是初始化列表构造函数,例如通过将参数类型包装在不能转换为 initializer-list 构造函数的元素类型的东西中:

#include <initializer_list>
#include <iostream>

namespace {

template<class T>
struct wrap
{
  T value;
};

class C {
public:
    C(C const &) = delete;
    C(C &&) = delete;
    C(wrap<int>) {
        std::cout << "int\n";
    }
    C(std::initializer_list<int>) {
        std::cout << "initializer\n";
    }
};

void f(C) {
}

// Compiles and prints "int" when called
C g() { return {wrap<int>{0}}; }

}   // namespace

int main() {
    // Compiles and prints "int"
    f({wrap<int>{0}});
    g();
}

打印出来:

int
int

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-14
    • 2022-11-21
    • 1970-01-01
    • 1970-01-01
    • 2015-06-10
    • 1970-01-01
    相关资源
    最近更新 更多