【问题标题】:Function to generate a tuple given a size N and a type T给定大小 N 和类型 T 生成元组的函数
【发布时间】:2016-05-07 21:31:53
【问题描述】:

在尝试回复 this question 时,我发现自己需要为可变参数函数创建一堆参数,其中:

  • 参数个数没有给出
  • 类型都相同,但未知(即使它们必须是默认可构造的)

在运行时,标准容器for循环可用于执行此操作。
无论如何,我想在编译时生成一组参数,以便能够将它们转发给可变参数函数。
因此,std::tuple 似乎是显而易见的解决方案。

这里出现了一个问题:在编译时给定大小 N 和默认可构造类型 T,我如何编写函数来生成给定大小的元组?

我正在寻找这样的东西:

auto tup = gen<MyType, N>();

在 SO 上是基于递归生成器的结构的 notable example,但我一直在努力使用基于函数的解决方案,但我无法在任何地方找到它。

【问题讨论】:

  • 如果类型都相同,我会使用 std::array&lt;T, N&gt; 而不是元组。
  • @davihigh 当然。我最终使用了一个元组,因为它确实更具挑战性。我这样做是为了实验,仅此而已。如果我遇到真正的问题,我也会使用array

标签: c++ templates c++14 variadic-templates stdtuple


【解决方案1】:

正确编写的转发函数(如std::apply)应该与std::array&lt;T, N&gt; 和任何其他实现std::tuple_size/std::get 接口的函数一起使用。也就是说,

template<size_t, class T>
using T_ = T;

template<class T, size_t... Is>
auto gen(std::index_sequence<Is...>) { return std::tuple<T_<Is, T>...>{}; }

template<class T, size_t N>
auto gen() { return gen<T>(std::make_index_sequence<N>{}); } 

【讨论】:

  • 你让我哭了!! :-) ...但至少尝试使用模板以如此复杂的方式完成如此简单的事情是很有趣的。
【解决方案2】:

以下是此类功能的可能实现:

#include<utility>
#include<tuple>

template<typename T>
constexpr auto
params(std::index_sequence<0>) {
    return std::tuple<T>{};
}

template<typename T, std::size_t I, std::size_t... O>
constexpr auto
params(std::index_sequence<I, O...>) {
    auto tup = std::tuple<T>{ T{} };
    auto seq = std::make_index_sequence<sizeof...(O)>{};
    return std::tuple_cat(tup, params<T>(seq));
}

template<typename T, std::size_t N>
constexpr auto
gen(std::integral_constant<std::size_t, N>) {
    return params<T>(std::make_index_sequence<N>{});
}

int main() {
    auto tup = gen<int>(std::integral_constant<std::size_t, 3>{});
    static_assert(std::tuple_size<decltype(tup)>::value == 3, "!");
}

为简单起见,我使用int 作为类型。
只需稍加努力,就可以使用用户定义的类型,并且可以放松让它们默认可构造的约束。

【讨论】:

    猜你喜欢
    • 2022-01-23
    • 2021-04-14
    • 1970-01-01
    • 2019-06-15
    • 2016-04-16
    • 2014-12-16
    • 1970-01-01
    • 1970-01-01
    • 2020-04-09
    相关资源
    最近更新 更多