【问题标题】:Is it possible to define a C++11 variadic class template whose variadic parameter cardinality depends on an integer template parameter?是否可以定义一个 C++11 可变参数类模板,其可变参数基数取决于整数模板参数?
【发布时间】:2012-10-10 09:43:45
【问题描述】:

对不起,这个复杂的问题,但基本上这个想法很简单。我有一个可变参数类模板:

template<class P1, class P2, class ... P3s>
class A 
{
    ...
};

我想要一个 A 类生成器,它接受一个整数模板参数 N 并用 N 个 P3s 参数实例化一个 A 类。喜欢:

template<class P1, class P2, class P3, int N>
class GenA : /* somehow */ : public A<P1, P2, /* N times */ P3, P3, ...>
{
    ...
};

所以用法是:

// Generates A<Class1, Class2, Class3, Class3, Class3>
GenA<Class1, Class2, Class3, 3> a; 

我已经尝试过使用编译时递归和部分特化来做到这一点

template <class P1, class P2, int N, class P3>
class GenA : public GenA<P1, P2, N-1, P3, P3>
{
    ...
}

template <class P1, class P2, int N, class ... P3s>
class GenA<P1, P2, 0, P3s ...> : public A<P1, P2, P3s, ...>
{
    ...
}

但是 C++11 不承认第二个模板是第一个模板的特化(因为它实际上是不同的)并且永远不会到达递归的基本情况(它停止抱怨太多递归级别)。有什么想法吗?

谢谢
图努兹

【问题讨论】:

  • 如果没有过多的模板专业化似乎很难做到。
  • 在你选择了一个答案后,你能提供一个解决方案的基准吗?

标签: c++ templates c++11


【解决方案1】:
template<class P1, class P2, class... P3s>
class A {};

template<class... Ps>
struct TypeList {};

template<class P1, class P2, class P3, unsigned N, class P> struct GenHelp;

template<class P1, class P2, class P3, class... Ps>
struct GenHelp<P1, P2, P3, 0, TypeList<Ps...> >
{
   typedef A<P1, P2, Ps... > AType;
};

template<class P1, class P2, class P3, unsigned N, class... Ps>
struct GenHelp<P1, P2, P3, N, TypeList<Ps...> > : public GenHelp<P1, P2, P3, N-1, TypeList<P3, Ps...> >
{};

template<class P1, class P2, class P3, unsigned N>
class GenA : public GenHelp<P1, P2, P3, N, TypeList<> >::AType
{};

【讨论】:

  • 太棒了!我会接受这个,因为它与我尝试做的类似。
【解决方案2】:

您可以使用可变参数模板模板参数来执行此操作。在这个 实现我们只需从一个参数包开始 P1P3 并继续扩展它。最后我们实例化 带有该参数包的可变参数模板模板参数。

template<class P1, class P2, class ... P3s>
struct A {};

template<template<class... Args> class AT, typename P3, int N, 
         typename... Already>
struct GenAImpl {
  typedef typename GenAImpl<AT, P3, N - 1, Already..., P3>::type type;
};

template<template<class... Args> class AT, typename P3, 
         typename... Already>
struct GenAImpl<AT, P3, 0, Already...> {
  typedef AT<Already...> type;
};


template<class P1, class P2, class P3, int N>
struct GenA : GenAImpl<A, P3, N, P1, P2>
{};

int main()
{
  GenA<int, double, float, 3>::type X;
  return 0;
}

请记住,附加到列表通常是一个坏主意(至少在 真正的函数式语言,我不知道这是否真的会影响 C++ 编译器性能)并且你最好将它组合在一起 并在最后反转它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    相关资源
    最近更新 更多