【问题标题】:Build a tuple recursively递归构建元组
【发布时间】:2016-05-15 18:45:08
【问题描述】:

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

这是我目前尝试过的

我主要做这样的事情

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...);
}

最终当没有更多参数时,将调用此函数(结束递归)

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 个参数,它会打印大小为 6 的元组,所以我相信它正在正确创建它。但是,我无法将其返回主函数。我不知道如何设置返回类型,以便正确地将最终元组带回上一个函数,然后返回主函数。

供参考,我使用的辅助'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)

【问题讨论】:

  • 如果您使用的是 c++14,那么 auto 就足够了...如果不是,您可以尝试将 auto-&gt; decltype() 结合起来,在 decltype 的括号中您应该通过调用生成元组的函数...
  • 你可以让函数返回类型为 auto 吗?编辑我一直在使用 c++11 但我会尝试 14
  • 是的,它应该被接受,因为编译器可以从返回语句中推断出结果...

标签: c++ templates recursion tuples variadic-templates


【解决方案1】:

我可以在您的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 的方式,但这是我脑海中第一个不需要大量额外输入的方法。 decltype/std::declval 位的本质是:给我在 std::string, T 元组上调用 std::tuple_cat 产生的类型,并将其递归结果应用于元组的其余部分。

【讨论】:

    【解决方案2】:

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

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

    从最后一个开始:

    return t;
    

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

    【讨论】:

    • 我试过了,但我只是不知道该怎么做。我尝试了一个可变参数模板,但是没有用
    • “制作”是什么意思?每个特定实例化的返回类型由编译器推断,当您想要实例化结果对象时,如果您不想枚举组成元组的所有字符串类型对,可以使用关键字auto
    猜你喜欢
    • 2023-01-28
    • 2020-01-19
    • 1970-01-01
    • 2011-10-26
    • 1970-01-01
    • 2013-01-12
    • 1970-01-01
    • 1970-01-01
    • 2014-07-17
    相关资源
    最近更新 更多