与非类型模板和返回元组的函数的简单混合混淆

Confused with simple mix of non-type templates and functions returning tuple

本文关键字:函数 简单 混合 元组 返回 类型      更新时间:2023-10-16

作为练习,我正在尝试编写 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<0>、...、Foo的元组

template <int N> struct Foo {
   static const int id = N;
}
template <template <int> class T, int N> 
constexpr ??? fun2 (???) {...}

由于模板化函数不能部分专用化,我什至不知道如何为我的递归编写适当的终止。我想完全静态地执行此操作,而不使用 for 循环。

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

===

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

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

首先,您可以使用 struct s 递归构建参数包以进行部分专用化(我向您展示这种方式是因为它与 #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 { };
}

对于第二种,您可以将上述技术与 int s 的参数包相结合,并使用...扩展它们,例如

Foo<Ints>...

扩展到

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

在您的函数中。