具有类模板的可变参数模板的特化

时间:2016-06-24 05:07:43

标签: c++ c++11 variadic-templates template-meta-programming template-templates

这是我在使用可变参数模板时遇到的问题。我有一些代码使用专门化来计算"有趣的"参数包中的类型如下:

template<typename... _Pp>
struct count;

template<>
struct count<>
{
  static const int value = 0;
};

// ignore uninteresting types
template<typename _First, typename... _Rest>
struct count<_First, _Rest...>
{
  static const int value = count<_Rest...>::value;
};

// add 1 for a pointer
template<typename _First, typename... _Rest>
struct count<_First*, _Rest...>
{
  static const int value = 1 + count<_Rest...>::value;
};

// add 1 for a reference
template<typename _First, typename... _Rest>
struct count<_First&, _Rest...>
{
  static const int value = 1 + count<_Rest...>::value;
};

// add 1 for an int
template<typename... _Rest>
struct count<int, _Rest...>
{
  static const int value = 1 + count<_Rest...>::value;
};

此代码工作正常,但如果我想使用相同的方法来计算类模板,我会遇到问题:

// add 1 for a vector
template<typename... _Rest>
struct count<vector, _Rest...>
{
  static const int value = 1 + count<_Rest...>::value;
};

上面的代码无法编译,错误是&#34;期望一个类型,得到'&#39;&#39;&#34;&#34;在&#34; struct count&#34;开头的行上。我也不能简单,所有类模板都接受一个参数:

// add 1 for a class template with 1 type parameter
template<template<typename> class _First, typename... _Rest>
struct count<_First, _Rest...>
{
  static const int value = 1 + count<_Rest...>::value;
}

这段代码也无法编译,抱怨&#34;期待一种类型,得到&#39; _First&#39;&#34;再次以&#34; struct count&#34;开头。有人熟悉使用这种方法实现这一目标的方法(即我可以对一个或两个特殊化进行一些修改,使它们在编译时编译并执行所需的计算)?

修改 我希望vector的参数包不被绑定,类似于以下代码,一个带有可变参数模板模板参数的简单容器包装器也专门用于std :: vector:

// pass a container as a parameter using variadic template-template 

parameter
template<typename _Tp, template<typename...> class _C>
struct success
{
  // not specialized for any container
  static const bool is_specialized = false;
  // data member of container type
  _C<_Tp> c_;
};

// partial specialization of above for std::vector
template<typename _Tp>
struct success<_Tp, std::vector>
{
  // specialized for vector
  static const bool is_specialized = true;
  // again, data member of container type
  std::vector<_Tp> c_;
};

修改 似乎最终的答案是我想要做的事情无法完成,但我找到了一种方法来重构问题,以便我能够解决它。非常感谢那些帮助过的人。

3 个答案:

答案 0 :(得分:2)

如果我理解你想要的东西......是的,你可以创建一个可以计算“类模板”的模板化结构,这样你就可以编写类似

的内容
 count<std::vector, std::map, std::set, std::pair>::value

但你不能混合类模板和简单的类型名,所以你不能写像

这样的东西
 count<std::vector, int &, float, std::set>::value

问题是,如果你定义

 template <typename... _Pp>
    struct count;

您可以将std::vector<int>传递给它,因为std::vector<int>typename,但您无法将std::vector传递给它,因为std::vector不是typename一个template<typename...> class;它是struct countC(或模板模板),它是完全不同的东西。

您可以编写类似以下template <template<typename...> class ...> struct countC; template <> struct countC<> { static const int value = 0; }; // ignore uninteresting templates template<template<typename...> class F, template<typename...> class ... R> struct countC<F, R...> { static const int value = countC<R...>::value; }; template <template<typename...> class ... R> struct countC<std::vector, R...> { static const int value = 1 + countC<R...>::value; };

的内容
struct count

以下是一个完整的工作示例,我已将struct countT重写为struct countC以查看所选类型的计数,我添加了struct countV来计算所选的“类模板”和我添加了#include <map> #include <set> #include <vector> #include <utility> #include <iostream> // countC for templates template <template<typename...> class ...> struct countC; template <> struct countC<> { static const int value = 0; }; // ignore uninteresting templates template<template<typename...> class F, template<typename...> class ... R> struct countC<F, R...> { static const int value = countC<R...>::value; }; template <template<typename...> class ... R> struct countC<std::vector, R...> { static const int value = 1 + countC<R...>::value; }; template <template<typename...> class ... R> struct countC<std::map, R...> { static const int value = 1 + countC<R...>::value; }; template <template<typename...> class ... R> struct countC<std::pair, R...> { static const int value = 1 + countC<R...>::value; }; // countV for for values of a fixed type template <typename T, T ... v> struct countV; template <typename T> struct countV<T> { static const int value = 0; }; // ignore uninteresting values template <typename T, T f, T ... r> struct countV<T, f, r...> { static const int value = countV<T, r...>::value; }; // count only int odd values template <int f, int ... r> struct countV<int, f, r...> { static const int value = (f % 2) + countV<int, r...>::value; }; // countT for typenames template <typename...> struct countT; template <> struct countT<> { static const int value = 0; }; // ignore uninteresting types template <typename F, typename ... R> struct countT<F, R...> { static const int value = countT<R...>::value; }; template <typename F, typename ... R> struct countT<F*, R...> { static const int value = 1 + countT<R...>::value; }; template<typename F, typename ... R> struct countT<F&, R...> { static const int value = 1 + countT<R...>::value; }; template<typename ... R> struct countT<int, R...> { static const int value = 1 + countT<R...>::value; }; int main() { std::cout << "countC vector + map + set + pair = " << countC<std::vector, std::map, std::set, std::pair>::value << std::endl; std::cout << "countT int + float + bool* + double& + bool + int& = " << countT<int, float, bool*, double&, bool, int&>::value << std::endl; std::cout << "countV int, 1 + 4 + 4 + 5 + 7 + 10 + 11 + 16 + 15 = " << countV<int, 1, 4, 4, 5, 7, 10, 11, 16, 15>::value << std::endl; std::cout << "countV long, 1 + 4 + 4 + 5 + 7 + 10 + 11 + 16 + 15 = " << countV<long, 1, 4, 4, 5, 7, 10, 11, 16, 15>::value << std::endl; return 0; } 来计算固定类型名称的选定值。

<input id="#avatar" type="file" onchange="previewFile()">

p.s:抱歉我的英语不好。

答案 1 :(得分:1)

这样的事情怎么样?

// add 1 for a vector
template<typename... _Rest, typename T>
struct count<vector<T>, _Rest...>
{
  static const int value = 1 + count<_Rest...>::value;
};

这个?

// add 1 for a class template with 1 type parameter
template<template<typename> class _First, typename T, typename... _Rest>
struct count<_First<T>, _Rest...>
{ 
  static const int value = 1 + count<_Rest...>::value;
};

答案 2 :(得分:1)

应该是:

template<typename... _Rest, typename... T>
struct count<std::vector<T...>, _Rest...>
{
    static const int value = 1 + count<_Rest...>::value;
};

通用版本:

template<template<typename...> class C, typename... _Rest, typename... T>
struct count<C<T...>, _Rest...>
{
    static const int value = 1 + count<_Rest...>::value;
};

Variadic pack重要。