【问题标题】:Confused with simple mix of non-type templates and functions returning tuple对非类型模板和返回元组的函数的简单混合感到困惑
【发布时间】:2013-01-30 04:06:29
【问题描述】:

作为练习,我正在尝试编写 2 个采用非类型模板 int N 的简单函数。 第一个需要创建一个由 T 类型对象的 N 个副本组成的元组。我希望它类似于以下内容:

template <class T, int N> 
constexpr std::tuple<T...> fun(T t) {
  return (N > 0) ? std::tuple_cat(t, fun<T, N-1>(t)) : std::make_tuple(t);
}

我也尝试过这样的事情,但没有成功 (http://liveworkspace.org/code/3LZ0Fe)。 我希望能够用 T = bool 来实例化它,比如:

auto bools = fun<bool, 10> (false);

第二个应该是轻微的变化;我有一个模板结构 Foo,我想创建一个包含 Foo, ..., Foo

的元组
template <int N> struct Foo {
   static const int id = N;
}

template <template <int> class T, int N> 
constexpr ??? fun2 (???) {...}

由于模板函数不能部分特化,我什至不知道如何为我的递归编写适当的终止。 我想完全静态地做到这一点,而不使用 for 循环。

================================================ ====================================

按照 Seth 的建议,我一直坚持编写无限递归的 fun 函数本身:

template<typename T, int N>
typename fun_helper<T, N>::type 
fun(T t) {
  if (N > 0) 
    return typename fun_helper<T, N>::type 
      { std::tuple_cat(std::make_tuple(t), fun<T, N-1>(t)) };
  else return typename fun_helper<T, N>::type { };
}

通过使用带有终止的附加结构,我能够得到这个工作:

template<typename T, int N> struct fun {
  typename fun_helper<T, N>::type make(T t) {
    return typename fun_helper<T, N>::type 
      { std::tuple_cat(std::make_tuple(t), fun<T, N-1>().make(t)) };
  }
};

template<typename T> struct fun<T, 0> {
  typename fun_helper<T, 0>::type 
  make(T t) {
    return typename fun_helper<T, 0>::type { };
  }
};

调用还是比较笨拙:

auto conds = fun<bool, 3>().make(false);

有没有办法让它在没有这个额外的结构的情况下工作?

auto conds = fun<bool, 3>(false);

【问题讨论】:

    标签: c++ tuples variadic-templates


    【解决方案1】:

    首先,您可以使用structs 递归地构建参数包以进行部分特化(我以这种方式向您展示,因为它与#2 相关)。此代码未经测试,不处理元素的默认值,但它为您提供了思路,并且可以轻松添加默认值代码。

    template<typename T, int N, typename... Rest>
    struct fun_helper {
        typedef typename fun_helper<T, N - 1, T, Rest...>::type type;
    };
    
    template<typename T, typename... Rest>
    struct fun_helper<T, 0, Rest...> {
        typedef std::tuple<Rest...> type;
    };
    
    template<typename T, int N>
    typename fun_helper<T, N>::type fun() {
        return typename fun_helper<T, N>::type { };
    }
    

    对于第二个,您可以将上述技术与ints 的参数包结合起来,并使用... 来扩展它们

    Foo<Ints>...
    

    扩展为

    Foo<Int1>, Foo<Int2>, ...
    

    在你的函数中。

    【讨论】:

    • 感谢 Seth,我现在看到了递归类型的构建。不幸的是,我需要更多的手,我似乎无法正确构建第一个乐趣(即给定 fun(T t) 创建正确的返回对象)...
    • @NickV 实际上该代码未经修改就可以工作,您应该像 auto t = fun&lt;bool, 4&gt;() 这样称呼它,它会使 t 成为 std::tuple&lt;bool, bool, bool, bool&gt;
    • 是的。我试图写乐趣(T t)。请参阅上面的更新。
    • @NickV 用你写的方式,你能不能把对 .make() 的调用移到函数内部?此外,您应该能够通过对值执行与对类型相同的操作来消除运行时递归和昂贵的 tuple_cat:使用模板递归地制作默认值的 N 个副本并一次制​​作最终的元组。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-22
    • 2011-06-10
    • 2014-10-08
    • 1970-01-01
    • 2014-07-28
    相关资源
    最近更新 更多