递归地构建元组

Build a tuple recursively

本文关键字:元组 构建 递归      更新时间:2023-10-16

给定一个参数包和一个字符串向量,我想递归地构建一个元组,每次获取每个元组的第一个,并将其附加到元组中。因此,如果我有一个向量,包含"string1"、"string2"、"string 3"和一个5、2.5、true的参数包。。。得到的元组将是"string1",5,"string2",2.5,"string3",true。

以下是我迄今为止尝试的

我主要做一些类似的事情

std::vector<std::string> string_vec; 
std::tuple<> t;
//initalize string_vec to something 
set_up_strings(string_vec);
//pass an empty tuple to start building with the strings and args
tuple_maker(t, string_vec, args...);

其中我的tuple_maker递归地添加其中的一个。

template<typename T, typename... Args, typename... Ts>
void tuple_maker(std::tuple<Ts...> t, std::vector<std::string> &vec, T value,  Args... args)
{
  auto newTup1 = tuple_append(t, vec.begin());
  auto newtup2 = tuple_append(newTup1, value);
  vec.erase(vec.begin());
//now pass in the vector and args after removing front of each
  tuple_maker(newtup2, vec,args...);
}

最终,当没有更多的args时,这个函数将被调用(结束递归)

template<typename... Ts>
std::tuple<Ts...> tuple_maker(std::tuple<Ts...> t, std::vector<std::string> &vec)
{
int tup_size = std::tuple_size<decltype(t)>::value;
std::cout<< "final tuple has size of " << tup_size << std::endl;
//return t;
}

如果我传入像string1-3这样的东西,以及前面提到的3个args,它会打印大小为6的元组,所以我相信它创建它是正确的。但是,我很难将它返回到主功能。我不知道如何设置返回类型,以便它能正确地将最后一个元组带回上一个函数,然后回到main。

作为参考,我使用的helper"tuple_maker"函数在这里是

template <typename NewType, typename... TupleElem>
std::tuple<TupleElem..., NewType> tuple_append(const std::tuple<TupleElem...> &tup, const NewType &n)
{
 return std::tuple_cat(tup, std::make_tuple(n));
}

我试过这样的东西。。。

template<typename T, typename... Args, typename... Ts, typename... ret>
std::tuple<ret...> tuple_maker(std::tuple<Ts...> t, std::vector<std::string> &vec, T value,  Args... args)

我可以在您的tuple_maker中看到几个可能的问题定义(为什么要将迭代器传递给tuple_append?),但它看起来你已经掌握了你要做的事情,所以我让你自己解决。

您的问题似乎是询问如何确定回报类型应该用于您的函数。有几种方法这

一个很简单但需要大量重复代码的方法是使用decltype使用尾随返回类型。然而,由于tuple_maker函数有多行代码,它可能最好用另一种方法。

在没有C++14的情况下(其中可以只使用auto作为返回值),你可以为你的函数创建一个类型生成器,如下所示:

#include <tuple>
#include <type_traits>
#include <utility>
template <typename>
struct RetMaker {
    using type = std::tuple<>;
};
template <typename T, typename... Rest>
struct RetMaker<std::tuple<T, Rest...>> {
    using rest = typename RetMaker<std::tuple<Rest...>>::type;
    using type = decltype(std::tuple_cat(
                              std::declval<std::tuple<std::string, T>>(),
                              std::declval<rest>()));
};

那么函数的返回类型是typename RetMaker<std::tuple<Ts...>>::type

我应该注意到,还有许多其他不同的方法可以实现这一点,包括在不使用std::tuple_cat的情况下执行do,但这是我脑海中第一个不需要大量额外键入的方法。decltype/std::declval位的本质是:给我在std::string, T元组上调用std::tuple_cat得到的类型,以及应用于元组其余部分的递归结果。

您应该从tuple_maker:的非最终版本返回一个值

return tuple_maker(newtup2, vec, args...);

最后一个:

return t;

这样,对tuple_maker的各种实例化的调用链就变成了一个尾部调用链,最后一个调用返回累加值。