我已经编写了一个类shrink_pair
,它的作用与pair
相同,但first
和second
是[[no_unique_address]]
。
我想写一个类似的构造函数,比如std::pair
的piecewise_construct
构造函数。这个构造函数应该通过拆包第一个和第二个元组并对元组元素进行转发((来调用first
和second
的构造函数。
std::apply
似乎对我不起作用,因为我调用的不是普通的可调用对象,而是构造函数。我该怎么做?
我相信这就是std::make_from_tuple
(C++17(的作用:
#include <tuple>
struct Foo {
Foo(int x, float y) {}
};
struct Bar {
Bar(int x, float y) {}
};
template <typename T, typename U>
struct Pair {
template <typename TupleT, typename TupleU>
Pair(TupleT&& first, TupleU&& second)
: first(std::make_from_tuple<T>(std::forward<TupleT>(first))),
second(std::make_from_tuple<U>(std::forward<TupleU>(second))) {}
T first;
U second;
};
int main() { Pair<Foo, Bar> p{std::tuple{1, 1.2f}, std::tuple{2, 2.0f}}; }
对于C++17以后的版本,请参阅@Quimby的答案。
对于C++11和C++14,您需要使用std::index_sequence
:以旧的方式执行
template <class U, class V>
class custom_pair {
template <std::size_t... UIs, std::size_t... VIs, class... UArgs, class... VArgs>
custom_pair(
std::index_sequence<UIs... >, std::tuple<UArgs... > u_args,
std::index_sequence<VIs... >, std::tuple<VArgs... > v_args) :
first(std::forward<UArgs>(std::get<UIs>(u_args))... ),
second(std::forward<VArgs>(std::get<VIs>(v_args))... ) { }
public:
U first;
V second;
public:
template <class... UArgs, class... VArgs>
custom_pair(std::piecewise_construct_t,
std::tuple<UArgs... > u_args,
std::tuple<VArgs... > v_args) :
custom_pair(
std::make_index_sequence<sizeof... (UArgs)>{}, std::move(u_args),
std::make_index_sequence<sizeof... (VArgs)>{}, std::move(v_args)) { }
};
该标准要求std::pair
等效构造函数适用于不可移动类型,因此您不能在C++14中使用中间函数(如自定义std::make_tuple
(,您必须在自定义对构造函数的初始值设定项列表中解包。
在C++17中,您可以使用std::make_tuple
这样的中间函数,因为您可以得到保证的副本省略,如@Quimby的答案所示。
导螺杆的完整示例:https://godbolt.org/z/7PsEjs18r