当前位置: 首页 > 知识库问答 >
问题:

变分模板与类模板的特殊化

夏奕
2023-03-14

这是我在玩变量模板时遇到的一个问题。我有一些代码,使用专业化来计算参数包中的“有趣”类型,就像这样:

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

上面的代码编译失败,错误是"预期的类型,得到了'向量'"开始的行"结构计数"。我也无法更简单的东西,所有的类模板接受一个参数:

// 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;
}

这段代码也无法编译,再次在以“结构计数”开头的行中抱怨“预期的类型,得到了‘_First’”。有人熟悉使用这种方法实现这一目标的方法吗(例如,我可以对一个或两个专业进行一些修改,使它们在编译时编译并执行所需的计算)?

编辑:我希望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个答案

拓拔俊德
2023-03-14

应该是:

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

变量包很重要。

法兴德
2023-03-14

像这样的怎么样?

// 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;
};
钱跃
2023-03-14

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

 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

您可以编写类似以下内容的代码

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

p、 对不起,我的英语不好。

 类似资料:
  • 我试图在类型s. t上专门化一个类。它忽略了给定类型的恒定性。在这种情况下,该类型是一个模板模板参数: 上面的代码在GCC 4.8.4和clang 5.0(with-std=c 11)中都抱怨bar在与匹配FOFType模板参数化的类一起使用时未定义。即使我删除了sfinae参数,仍然无法找到特化。 这个问题的一个例子可以在这里找到:https://godbolt.org/g/Cjci9C.在上面

  • 2.2.1 根据类型执行代码 前一节的示例提出了一个要求:需要做出根据类型执行不同代码。要达成这一目的,模板并不是唯一的途径。比如之前我们所说的重载。如果把眼界放宽一些,虚函数也是根据类型执行代码的例子。此外,在C语言时代,也会有一些技法来达到这个目的,比如下面这个例子,我们需要对两个浮点做加法, 或者对两个整数做乘法: struct Variant { union { int x

  • YDoc 主题的模板是若干的 jsx 组件,以下是各模板文件相对应的功能(按首字母排序): 模板 功能 Content.jsx 文档页内容 Footer.jsx (用户自定义组件) Footer 信息 Head.jsx html 文件中 部分的内容 Header.jsx 顶部导航 Homepage.jsx (用户自定义组件) 文档站首页 Hook.jsx 钩子,用于自定义插件 Icon.jsx f

  • 在C++11之前,类模板和函数模板只能含有固定数量的模板参数。C++11增强了模板功能,允许模板定义中包含0到任意个模板参数,这就是可变参数模板。可变参数模板的加入使得C++11的功能变得更加强大,而由此也带来了许多神奇的用法。 可变参数模板 可变参数模板和普通模板的语义是一样的,只是写法上稍有区别,声明可变参数模板时需要在typename或class后面带上省略号...: template<ty

  • 是否有人知道此显式特化是否有效: clang 主干 (12/3/2013) 给出以下错误: f:...\test.cpp:36:20: 错误: 从类 'O' 中出线定义 “Fun” 没有定义 1生成错误。 任何来自标准的支持参考来证明你的答案将不胜感激! 注意:我有点惊讶这是一个错误——我认为应该为任何以< code >开始实例化“Fun”的模板参数族选择专门化 这是一个叮当的错误还是我期望中的错

  • Postfix Completion 的介绍 Postfix Completion 功能本质上也是代码模板,只是它比 Live Templates 来得更加便捷一点点而已。具体它是做什么的,我们通过下面一张 Gif 演示图来说明: 如上图标注 1 所示,非空的判断在 Java 代码中应该是非常常见的一句话代码,如果用 Live Templates 当然也是可以快速生成,但是没有上图 Gif 这种