如何在调用构造函数时展开 std::tuple<...>

  • 本文关键字:tuple std 调用 构造函数 c++
  • 更新时间 :
  • 英文 :


我已经编写了一个类shrink_pair,它的作用与pair相同,但firstsecond[[no_unique_address]]

我想写一个类似的构造函数,比如std::pairpiecewise_construct构造函数。这个构造函数应该通过拆包第一个和第二个元组并对元组元素进行转发((来调用firstsecond的构造函数。

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

相关内容