C++17 make_tuple来自参数包

C++17 make_tuple from an argument pack

本文关键字:参数 tuple make C++17      更新时间:2023-10-16

我想执行以下操作,但不知道为什么它在 C++17 中没有编译。

int func(int a) {
// do some operations on a
int res = operation_on_a(a);
return res;
}
auto funcs(int... as) {
return make_tuple(func(as)...);
}
auto v1 = func(1);
auto [v1, v2, v3] = funcs(1, 2, 3);  // Why this doesn't compile?

基本上,这个想法是让一个名为func()的基本函数和另一个采用可变参数的函数将每个项目应用于func()并返回结果的std::tuple。但是,除非我用模板类型替换int...,否则它不会被编译。在这种情况下,我知道参数都是整数。

我想

执行以下操作,但不知道为什么它没有在 C++17 中编译。

仅仅因为

auto funcs(int... as) {
return make_tuple(func(as)...);
}

不是C++语法。

我认为

template <typename Args>
auto funcs (Args ... as)
{ return std::make_tuple(func(as)...); }

考虑到每个返回intas...调用func(),是一个合理的解决方案。

但是,如果你真的想要一个像可变参数函数一样接受可变参数数int的东西(并且如果你可以为参数数量设置上限),我提出以下解决方案。

首先,你需要一个接收类型和std::size_t并返回类型的模板;类似于

template <typename T, std::size_t>
using typer = T;

现在是具有自继承的帮助程序递归struct

template <typename>
struct bar;
template <>
struct bar<std::index_sequence<>>
{ 
static void f () {}
};
template <std::size_t ... Is>
struct bar<std::index_sequence<Is...>>
: public bar<std::make_index_sequence<sizeof...(Is)-1U>>
{
using bar<std::make_index_sequence<sizeof...(Is)-1U>>::f;
static auto f (typer<int, Is>... as)
{ return std::make_tuple(func(as)...); }
};

使用static方法定义一个barstruct序列,f接收一些int(typer<int, Is>int)。

现在是struct foo

template <std::size_t N = 64U>
struct foo : public bar<std::make_index_sequence<N>>
{ };

继承自barstructs 序列并继承接收零、1、2、...、N-1ints 的f()序列。

现在您可以致电

auto [v1, v2, v3] = foo<>::f(1, 2, 3);

因为在foostruct中(也)有一个f()方法,它正好接收三个int

以下是完整的工作示例

#include <tuple>
#include <iostream>
#include <type_traits>
int func(int a)
{ return a+1; }
template <typename T, std::size_t>
using typer = T;
template <typename>
struct bar;
template <>
struct bar<std::index_sequence<>>
{ 
static void f () {}
};
template <std::size_t ... Is>
struct bar<std::index_sequence<Is...>>
: public bar<std::make_index_sequence<sizeof...(Is)-1U>>
{
using bar<std::make_index_sequence<sizeof...(Is)-1U>>::f;
static auto f (typer<int, Is>... as)
{ return std::make_tuple(func(as)...); }
};
template <std::size_t N = 64U>
struct foo : public bar<std::make_index_sequence<N>>
{ };
int main ()
{    
auto [v1, v2, v3] = foo<>::f(1, 2, 3);
std::cout << v1 << ", " << v2 << ", " << v3 << std::endl;
}