如何创建一个不可复制对象的元组

huangapple go评论92阅读模式
英文:

How to create a tuple of non-copyable objects

问题

我正在尝试创建一个不可复制对象的元组。当我有复制构造函数时,我能够构造元组。但当它们被删除时,编译会失败。

我能够通过添加元组构造函数来使其工作。这不是理想的解决方案,因为它要求将此构造函数添加到所有我的类中。是否有任何不需要更改元组中的对象的解决方案?谢谢!

英文:

I'm trying to create a tuple of non-copyable objects. When I have the copy-constructor in-place, I'm able to construct the tuple. When they are deleted, the compilation fails.

#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;
}

I was able to get this to work by adding a tuple constructor.

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_;
};

This is not ideal since it requires adding this constructor to all my classes. Is there any solution which does not require altering the objects in the tuple? Thanks!

答案1

得分: 1

有一种在C++17中的方法。在C++11/14中不起作用,因为在C++17中强制使用RVO。

需要一个中间类 C 用于构造 A。在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;
}
英文:

There is a way in C++17. Doesn't work in C++11/14 as in C++17 RVO is mandated.

It requires an intermediate class C that is used to construct A. In prior versions to C++17 you'd have to add an additional constructor to A.

#include &lt;tuple&gt;
#include &lt;iostream&gt;
#include &lt;utility&gt;

struct A {
    int&amp; x;
    int&amp; y;

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

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

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

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

If you were to use std::pair instead of std::tuple, you could achieve it as well via std::piecewise_construct. See,

#include &lt;tuple&gt;
#include &lt;iostream&gt;
#include &lt;utility&gt;

struct A {
    int&amp; x;
    int&amp; y;

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


class B {
private:
    std::pair&lt;A, A&gt; a_b_;
public:
    B(int&amp; w, int&amp; x, int&amp; y, int&amp; 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;
}

huangapple
  • 本文由 发表于 2023年4月11日 06:12:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/75981113.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定