用它的索引范围打包元组
Pack tuple with its index range
我想知道是否有一种方法可以将元组与其索引范围打包(可能使用 std::index_sequence
)。基本上,我想要实现的是
template <typename... Us, std::size_t... Idx>
void func(??? arg_pack) {
// std::get<Idx>(std::move(arg_pack.args))...
}
以下不成立,但表明我的意图。
template <typename... Us, std::size_t... Idx>
struct arg_pack {
std::tuple<Us...> args;
std::index_sequence<Idx...> idx;
};
更新:
This is the solution I practically adopted with sample usage。希望这能更清楚地说明我的意图。
双可变列表有一个常见的问题:可变参数的末尾只能有一个。
我建议将索引列表打包成一个类型(通常的std::index_sequence
)放在首位
我的意思是,类似
template <typename...>
struct arg_pack;
template <std::size_t ... Is, typename ... Ts>
struct arg_pack<std::index_sequence<Is...>, Ts...>
{
static_assert( sizeof...(Is) == sizeof...(Ts) , "!" );
std::tuple<Ts...> args;
std::index_sequence<Is...> idx;
};
所以func()
可以这样写
template <std::size_t ... Is, typename ... Ts>
void func (arg_pack<std::index_sequence<Is...>, Ts...> && ap)
{
using unused = int[];
(void)unused { 0, (std::get<Is>(std::move(ap.args)), 0)... };
}
我还建议声明(不是定义,以 std::declval()
的方式......但你也可以创建一个 make_arg_pack()
以从 [=19= 的列表开始创建对象] 值)declArgPack()
函数
template <typename ... Ts>
arg_pack<std::make_index_sequence<sizeof...(Ts)>, Ts...> declArgPack ();
简化类型的创建,并定义模板using
类型,简化使用declArgPack()
template <typename ... Ts>
using arg_pack_type = decltype(declArgPack<Ts...>());
以下是完整的工作示例
#include <tuple>
#include <type_traits>
template <typename...>
struct arg_pack;
template <std::size_t ... Is, typename ... Ts>
struct arg_pack<std::index_sequence<Is...>, Ts...>
{
static_assert( sizeof...(Is) == sizeof...(Ts) , "!" );
std::tuple<Ts...> args;
std::index_sequence<Is...> idx;
};
template <typename ... Ts>
arg_pack<std::make_index_sequence<sizeof...(Ts)>, Ts...> declArgPack ();
template <typename ... Ts>
using arg_pack_type = decltype(declArgPack<Ts...>());
template <std::size_t ... Is, typename ... Ts>
void func (arg_pack<std::index_sequence<Is...>, Ts...> && ap)
{
using unused = int[];
(void)unused { 0, (std::get<Is>(std::move(ap.args)), 0)... };
}
int main ()
{
arg_pack_type<short, int, long, long long> ap0;
func(std::move(ap0));
}
我想知道是否有一种方法可以将元组与其索引范围打包(可能使用 std::index_sequence
)。基本上,我想要实现的是
template <typename... Us, std::size_t... Idx>
void func(??? arg_pack) {
// std::get<Idx>(std::move(arg_pack.args))...
}
以下不成立,但表明我的意图。
template <typename... Us, std::size_t... Idx>
struct arg_pack {
std::tuple<Us...> args;
std::index_sequence<Idx...> idx;
};
更新:
This is the solution I practically adopted with sample usage。希望这能更清楚地说明我的意图。
双可变列表有一个常见的问题:可变参数的末尾只能有一个。
我建议将索引列表打包成一个类型(通常的std::index_sequence
)放在首位
我的意思是,类似
template <typename...>
struct arg_pack;
template <std::size_t ... Is, typename ... Ts>
struct arg_pack<std::index_sequence<Is...>, Ts...>
{
static_assert( sizeof...(Is) == sizeof...(Ts) , "!" );
std::tuple<Ts...> args;
std::index_sequence<Is...> idx;
};
所以func()
可以这样写
template <std::size_t ... Is, typename ... Ts>
void func (arg_pack<std::index_sequence<Is...>, Ts...> && ap)
{
using unused = int[];
(void)unused { 0, (std::get<Is>(std::move(ap.args)), 0)... };
}
我还建议声明(不是定义,以 std::declval()
的方式......但你也可以创建一个 make_arg_pack()
以从 [=19= 的列表开始创建对象] 值)declArgPack()
函数
template <typename ... Ts>
arg_pack<std::make_index_sequence<sizeof...(Ts)>, Ts...> declArgPack ();
简化类型的创建,并定义模板using
类型,简化使用declArgPack()
template <typename ... Ts>
using arg_pack_type = decltype(declArgPack<Ts...>());
以下是完整的工作示例
#include <tuple>
#include <type_traits>
template <typename...>
struct arg_pack;
template <std::size_t ... Is, typename ... Ts>
struct arg_pack<std::index_sequence<Is...>, Ts...>
{
static_assert( sizeof...(Is) == sizeof...(Ts) , "!" );
std::tuple<Ts...> args;
std::index_sequence<Is...> idx;
};
template <typename ... Ts>
arg_pack<std::make_index_sequence<sizeof...(Ts)>, Ts...> declArgPack ();
template <typename ... Ts>
using arg_pack_type = decltype(declArgPack<Ts...>());
template <std::size_t ... Is, typename ... Ts>
void func (arg_pack<std::index_sequence<Is...>, Ts...> && ap)
{
using unused = int[];
(void)unused { 0, (std::get<Is>(std::move(ap.args)), 0)... };
}
int main ()
{
arg_pack_type<short, int, long, long long> ap0;
func(std::move(ap0));
}