模板的特化和萃取

2024-04-09 13:32
文章标签 模板 特化 萃取

本文主要是介绍模板的特化和萃取,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

之前对模板化编程进行了总结(详见https://blog.csdn.net/timecur/article/details/89949643)。这篇将介绍模板的重要概念---模板特化。

模板的特化

        模板针对某些具体的类型不能处理或者处理结果有误,就需要进行模板特化。

// 例如一个比较两元素大小的模板
template<class T>
T& Max(T& left, T& right){return left > right ? left : right;
}// 模板特化
template<>  
char*& Max<char*>(char*& left, char*& right){if(strcmp(left, right) > 0)return left;return right;
}int main(){char* p1 = "world";char* p2 = "hello";std::cout << Max(p1, p2) << std::endl;  // 输出结果永远是p1的值, 因为它是将p1与p2的地址进行比较
}

函数模板的特化步骤:

  1. 必须先要定义一个函数模板
  2. 不能处理的类型进行特化
// 特化方式
template<>
返回值类型 FuncName<特化类型>(参数列表)
{}

注意: 特化版本必须与模板函数的原型要一致;

            特化比较麻烦,如果特化不了,可以直接将该类型的函数直接给出。

  • 全特化

        全特化:将模板参数类表中所有的参数都确定化。

   样例代码:

template<class T1, class T2>
class Data{
public: Data() {cout<<"Data<T1, T2>" <<endl;}
private: T1 _d1; T2 _d2;
};template<>
class Data<int, char>{
public:Data() {cout<<"Data<int, char>" <<endl;}
private: T1 _d1; T2 _d2;
};
void TestVector(){ Data<int, int> d1; Data<int, char> d2;
}

 

  • 偏特化

        偏特化:将模板参数列表的部分参数特化

   样例代码:

// 将第二个参数特化为int
template <class T1>
class Data<T1, int>{
public:Data() {cout<<"Data<T1, int>" <<endl;}
private:T1 _d1;int _d2;
}; 

        使模板参数限制更加严格。

   样例代码:

//两个参数偏特化为指针类型
template <typename T1, typename T2>
class Data <T1*, T2*>{ 
public:Data() {cout<<"Data<T1*, T2*>" <<endl;}private:T1 _d1;T2 _d2;
}//两个参数偏特化为引用类型
template <typename T1, typename T2>
class Data <T1&, T2&>
{
public:Data(const T1& d1, const T2& d2): _d1(d1), _d2(d2){cout<<"Data<T1&, T2&>" <<endl;}private:const T1 & _d1;const T2 & _d2; };
void test2 () 
{Data<double , int> d1; // 调用特化的int版本Data<int , double> d2; // 调用基础的模板 Data<int *, int*> d3; // 调用特化的指针版本Data<int&, int&> d4(1, 2); // 调用特化的指针版本
}

        可以看出指针或是引用类型的特化更多的是对类型做了某些限定,但仍保留了一定的模板性,但这种特化提供了极大的方便。

        注: 严格来说,函数模板并不支持偏特化,但由于可以对函数进行重载,所以可以达到类似于类模板偏特化的效果。

 

  • 类型萃取

       类型萃取可以说是模板特化的应用衍生出的概念。具体来说就是萃取某一特定类型,将该类型进行特殊的处理,以此来提高运行效率。

      使用类型萃取能提供一种根据类型的某些属性在编译时期进行函数派送的机制,减少代码混乱。

    代码演示说明(例实现通用拷贝函数):

  • 有上述概念可知,我们需要对特定类型进行萃取,从而进行特殊处理。数据类型可分为内置类型和自定义类型,那好我们就对这两种类型进行类型萃取。

        首先定义两种类型:

 struct TrueType {};  // 内置类型struct FalseType{};  // 自定义类型
  • 特化需要处理的类型。
template <class T>
struct TypeTraits
{typedef __FalseType IsPodType;
};// 对字符型进行特化
template <>
struct TypeTraits <char>
{typedef __TrueType IsPodType;
};// 其他内置类型特化方式类似不再赘述 ...
  • 通过函数派送机制,避免使用if/else语句来判断是内置类型或自定义类型。再通过不同的类型调用特定的方法。
template <class T>
inline T* TypeCopy(const T* src, T* dst, size_t n)
{return __TypeCopy(src, dst, n, TypeTraits<T>::IsPodType());
}
  • 通过重载实现不同类型的不同拷贝方法。

       内置类型可以通过memcpy方式进行拷贝。而自定义类型可能涉及资源的管理,所以用memcpy会出现浅拷贝问题,所以在这里使用深拷贝的方式处理。

template <class T>
inline T* __TypeCopy(const T* src, T* dst, size_t n, __TrueType)		
{cout << "内置类型拷贝:" << typeid(T).name() << endl;return (T*)memcpy(dst, src, sizeof(T) * n);
}template <class T>
inline T* __TypeCopy(const T* src, T* dst, size_t n, __FalseType)	
{cout << "自定义类型拷贝:" << typeid(T).name()<< endl;for (size_t i = 0; i < n; i++){dst[i] = src[i];}return dst;
} 

        typeid(Type).name() ---> 以字符串返回类型名

这篇关于模板的特化和萃取的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/888282

相关文章

离心萃取机废旧磷酸铁锂电池回收工艺流程

在废旧磷酸铁锂电池的回收工艺流程中,离心萃取机主要应用于萃取除杂的步骤,以提高回收过程中有价金属(如锂)的纯度。以下是结合离心萃取机应用的废旧磷酸铁锂电池回收工艺流程: 电池拆解与预处理 拆解:将废旧磷酸铁锂电池进行拆解,分离出电池壳、正负极片、隔膜等部分。破碎与筛分:将正负极片进行破碎处理,并通过筛分将不同粒径的物料分开,以便后续处理。 浸出与溶解 浸出:采用适当的浸出工艺(如二段式逆

poj3468(线段树成段更新模板题)

题意:包括两个操作:1、将[a.b]上的数字加上v;2、查询区间[a,b]上的和 下面的介绍是下解题思路: 首先介绍  lazy-tag思想:用一个变量记录每一个线段树节点的变化值,当这部分线段的一致性被破坏我们就将这个变化值传递给子区间,大大增加了线段树的效率。 比如现在需要对[a,b]区间值进行加c操作,那么就从根节点[1,n]开始调用update函数进行操作,如果刚好执行到一个子节点,

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

uva 1342 欧拉定理(计算几何模板)

题意: 给几个点,把这几个点用直线连起来,求这些直线把平面分成了几个。 解析: 欧拉定理: 顶点数 + 面数 - 边数= 2。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#inc

uva 11178 计算集合模板题

题意: 求三角形行三个角三等分点射线交出的内三角形坐标。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <

poj 2104 and hdu 2665 划分树模板入门题

题意: 给一个数组n(1e5)个数,给一个范围(fr, to, k),求这个范围中第k大的数。 解析: 划分树入门。 bing神的模板。 坑爹的地方是把-l 看成了-1........ 一直re。 代码: poj 2104: #include <iostream>#include <cstdio>#include <cstdlib>#include <al

最大流、 最小费用最大流终极版模板

最大流  const int inf = 1000000000 ;const int maxn = 20000 , maxm = 500000 ;struct Edge{int v , f ,next ;Edge(){}Edge(int _v , int _f , int _next):v(_v) ,f(_f),next(_next){}};int sourse , mee

C++语法知识点合集:11.模板

文章目录 一、非类型模板参数1.非类型模板参数的基本形式2.指针作为非类型模板参数3.引用作为非类型模板参数4.非类型模板参数的限制和陷阱:5.几个问题 二、模板的特化1.概念2.函数模板特化3.类模板特化(1)全特化(2)偏特化(3)类模板特化应用示例 三、模板分离编译1.概念2.模板的分离编译 模版总结 一、非类型模板参数 模板参数分类类型形参与非类型形参 非类型模板

Smarty模板引擎工作机制(一)

深入浅出Smarty模板引擎工作机制,我们将对比使用smarty模板引擎和没使用smarty模板引擎的两种开发方式的区别,并动手开发一个自己的模板引擎,以便加深对smarty模板引擎工作机制的理解。 在没有使用Smarty模板引擎的情况下,我们都是将PHP程序和网页模板合在一起编辑的,好比下面的源代码: <?php$title="深处浅出之Smarty模板引擎工作机制";$content=