c++ 如何创建不可复制对象的元组

u4dcyp6a  于 2023-04-13  发布在  其他
关注(0)|答案(2)|浏览(138)

我试图创建一个不可复制对象的元组。当我有复制构造函数时,我就可以构造元组。当它们被删除时,编译失败。

#include <tuple>
#include <iostream>
#include <utility>

struct A {
    int& x;
    int& y;

    A(int& a, int& b) : x(a), y(b) {}
    A(const A&) = delete;
    A& operator=(const A&) = delete;
};

class B {
public:
    B(int& w, int& x, int& y, int& z)
    : a_b_{ A(w,x),A(y,z)} {}
    
private:
    std::tuple<A, A> a_b_;
};

int main() {
    int w =1, x=2, y=3, z=4;
    B b{w,x,y,z};
    return 0;
}

我可以通过添加一个元组构造函数来实现这一点。

struct A {
    int& x;
    int& y;

    A(int& a, int& b) : x(a), y(b) {}
    A(const A&) = delete;
    A& operator=(const A&) = delete;

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

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

};

class B {
public:
    B(int& w, int& x, int& y, int& z)
    : a_b_{ std::forward_as_tuple(w,x), std::forward_as_tuple(y,z)} {}
    
private:
    std::tuple<A, A> a_b_;
};

这并不理想,因为它需要将这个构造函数添加到我所有的类中。有没有不需要改变元组中对象的解决方案?谢谢!

7vux5j2d

7vux5j2d1#

在C17中有一种方法。在C11/14中不起作用,因为在C17中RVO是强制性的。
它需要一个用于构造A的中间类C。在C
17之前的版本中,必须向A添加一个额外的构造函数。

#include <tuple>
#include <iostream>
#include <utility>

struct A {
    int& x;
    int& y;

    A(int& a, int& b) : x(a), y(b) {}
    A(const A&) = delete;
    A& operator=(const A&) = delete;
};

struct C {
    int* x;
    int* y;
    
    C(int& a, int& b) : x(&a), y(&b) {};
    
    operator A () const
    {
        return A(*x,*y);
    }
};

class B {
public:
    B(int& w, int& x, int& y, int& z)
    : a_b_{ C{w,x}, C{y,z}} {}
    
private:
    std::tuple<A, A> a_b_;
};

int main() {
    int w =1, x=2, y=3, z=4;
    B b{w,x,y,z};
    return 0;
}

如果你使用std::pair而不是std::tuple,你也可以通过std::piecewise_construct来实现。

#include <tuple>
#include <iostream>
#include <utility>

struct A {
    int& x;
    int& y;

    A(int& a, int& b) : x(a), y(b) {}
    A(const A&) = delete;
    A& operator=(const A&) = delete;
};

class B {
private:
    std::pair<A, A> a_b_;
public:
    B(int& w, int& x, int& y, int& z)
    : a_b_{std::piecewise_construct, std::forward_as_tuple(w,x),  std::forward_as_tuple(y,z)} {}
};

int main() {
    int w =1, x=2, y=3, z=4;
    B b{w,x,y,z};
    return 0;
}
vqlkdk9b

vqlkdk9b2#

元组中的对象使用std::reference_wrapper。你需要解决的唯一问题是将A类对象本身存储在某个地方。你可以通过两种方式来实现这一点:
在类B中添加局部变量来存储它们:

class B {
private:
    A a_, b_;

    std::tuple <std::reference_wrapper<A>, std::reference_wrapper<A> > a_b_;
public:
    B(int& w, int& x, int& y, int& z)
        : a_(w, x), b_(y, z), a_b_(std::forward_as_tuple(a_, b_)) {}
};

相关问题