模板的特化和萃取

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

相关文章

Java如何根据word模板导出数据

《Java如何根据word模板导出数据》这篇文章主要为大家详细介绍了Java如何实现根据word模板导出数据,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... pom.XML文件导入依赖 <dependency> <groupId>cn.afterturn</groupId>

Python中Flask模板的使用与高级技巧详解

《Python中Flask模板的使用与高级技巧详解》在Web开发中,直接将HTML代码写在Python文件中会导致诸多问题,Flask内置了Jinja2模板引擎,完美解决了这些问题,下面我们就来看看F... 目录一、模板渲染基础1.1 为什么需要模板引擎1.2 第一个模板渲染示例1.3 模板渲染原理二、模板

利用Python打造一个Excel记账模板

《利用Python打造一个Excel记账模板》这篇文章主要为大家详细介绍了如何使用Python打造一个超实用的Excel记账模板,可以帮助大家高效管理财务,迈向财富自由之路,感兴趣的小伙伴快跟随小编一... 目录设置预算百分比超支标红预警记账模板功能介绍基础记账预算管理可视化分析摸鱼时间理财法碎片时间利用财

如何在 Spring Boot 中实现 FreeMarker 模板

《如何在SpringBoot中实现FreeMarker模板》FreeMarker是一种功能强大、轻量级的模板引擎,用于在Java应用中生成动态文本输出(如HTML、XML、邮件内容等),本文... 目录什么是 FreeMarker 模板?在 Spring Boot 中实现 FreeMarker 模板1. 环

IDEA自动生成注释模板的配置教程

《IDEA自动生成注释模板的配置教程》本文介绍了如何在IntelliJIDEA中配置类和方法的注释模板,包括自动生成项目名称、包名、日期和时间等内容,以及如何定制参数和返回值的注释格式,需要的朋友可以... 目录项目场景配置方法类注释模板定义类开头的注释步骤类注释效果方法注释模板定义方法开头的注释步骤方法注

C++中函数模板与类模板的简单使用及区别介绍

《C++中函数模板与类模板的简单使用及区别介绍》这篇文章介绍了C++中的模板机制,包括函数模板和类模板的概念、语法和实际应用,函数模板通过类型参数实现泛型操作,而类模板允许创建可处理多种数据类型的类,... 目录一、函数模板定义语法真实示例二、类模板三、关键区别四、注意事项 ‌在C++中,模板是实现泛型编程

基于Java实现模板填充Word

《基于Java实现模板填充Word》这篇文章主要为大家详细介绍了如何用Java实现按产品经理提供的Word模板填充数据,并以word或pdf形式导出,有需要的小伙伴可以参考一下... Java实现按模板填充wor编程d本文讲解的需求是:我们需要把数据库中的某些数据按照 产品经理提供的 word模板,把数据

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

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

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 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�