英文:
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 <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;
}
If you were to use std::pair
instead of std::tuple
, you could achieve it as well via std::piecewise_construct
. See,
#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;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论