繁体   English   中英

初始化不可复制和不可移动类的元组

[英]Initialize a tuple of non-copyable and non-movable classes

考虑具有唯一自定义构造函数的类A:

class A
{
public:
    A(float) {}

private:
    A() = delete;
    A(const A&) = delete;
    A(A&&) = delete;
};

还有另一个类B,其中包含A的元组(为简单起见,请使其成为唯一的元组成员):

class B
{
public:
    B() : ta(0.0f) {} // ta initialization OK

private:
    std::tuple<A> ta;
};

现在我们可以声明B的对象,并且可以正常工作:

B b;

但是,如果A的构造函数具有多个参数,该如何做呢?

class A
{
public:
    A(float, int) {}

private:
    A() = delete;
    A(const A&) = delete;
    A(A&&) = delete;
};

class B
{
public:
//  B() : ta(0.0f, 1) {} // Compilation errors
//  B() : ta({0.0f, 1}) {} // Compilation errors
//  B() : ta{0.0f, 1} {} // Compilation errors
//  B() : ta(A(0.0f, 1)) {} // No constructor to copy or move A

private:
    std::tuple<A> ta;
};

B b;

std::make_tuplestd::forward_as_tuple和其他类似的方法都不能解决问题,因为默认情况下, A复制,构造函数和移动构造器均被禁用。

std::tuple很少有用于就地构建其成员的设施。 通常,初始化tuple是通过从其组件对象复制/移动。

它确实允许将构造函数参数隐式转换为它们各自的参数。 但这只是参数和tuple成员之间的1:1关系。 构造函数参数和tuple成员之间没有多对一的关系。

可以允许从tuple本身隐式构造您的类型:

class A
{
public:
    A(float, int) {}
    A(const std::tuple<float, int> &tpl)
        : A(std::get<0>(tpl), std::get<1>(tpl)) {}

private:
    A() = delete;
    A(const A&) = delete;
    A(A&&) = delete;
};

因此,您可以像这样构造一个tuple

class B
{
public:
    B() : ta(std::tuple<float, int>(0.0f, 1)) {}

private:
    std::tuple<A> ta;
};

如果要使用更深入的元编程,则可能仍可以创建一组构造函数,以允许从其类型与任何可用构造函数匹配的tuple构造类型:

class A
{
public:
    A(float, int) {}

    template<typename ...Args>
    A(const std::tuple<Args...> &args) : A(args, std::index_sequence_for<Args...>{}) {}

private:
    A() = delete;
    A(const A&) = delete;
    A(A&&) = delete;

    template<typename ...Args, std::size_t ...Is>
    A(const std::tuple<Args...> &args, std::index_sequence<Is...>) 
        : A(std::get<Is>(args)...) {}
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM