【C/C++基础进阶系列】C/C++ 泛型 -- 函数模板
发布日期:2021-05-07 20:53:16 浏览次数:24 分类:精选文章

本文共 4481 字,大约阅读时间需要 14 分钟。

【C/C++基础进阶系列】C/C++ 泛型 -- 函数模板

【C/C++基础进阶系列】C/C++ 泛型 -- 函数模板

【1】函数模板 -- 基础与实例化

#include

using namespace std;

// 基本范例// a) 模板的定义是以template关键字开头// b) 类型模板参数T前面用typename来修饰,因此遇到typename就该知道其后面跟的是一个类型// c) 类型模板参数T(代表是一个类型)包括前面的修饰符typename/class都用<>括起来// d) T这个名字可以换成任意其他标识符,对程序没有影响,用T只是一种编程习惯

namespace _nmsp1 {// template

// void T mydouble(T tmpvalue) { return tmpvalue * 2; }// template
// double mydouble(t tmpvalue) { return tmpvalue * 2; }template
T mydouble(t tmpvalue) { return tmpvalue * 2; }template
double mydouble(t tmpvalue) { return tmpvalue * 2; }}

// 实例化// 实例化,编译时,用具体的“类型”代替“类型模板参数”的过程就叫做实例化(也称为代码生成器)// .obj文件在编译完成后就会产生// .obj文件的格式一般会被认为是一种COFF——通用对象文件格式(Common Object File Format);

int main() {// int Sub

(3, 5)// double Sub
(4.7, 2.1)// int Sub
(3, 5.9)// 可以强制类型转换// double Sub
(3, 5.9)

// 在编译阶段,编译器需要能够找到函数模板的函数体部分// string a("abc"), b("def");// string addresult = Sub(a, b); // 编译器报错,string类型相减不合法// 合法性的判断在编译阶段判定

}

【2】函数模板 -- 模板参数的推断

#include

using namespace std;

namespace _nmsp1 {template <typename v, typename t, typename u>V Add(T tv1, U tv2) {return tv1 + tv2;}

// 模板参数的推断// 常规的参数推断// 通过<>可以只指定一部分模板参数的类型,另外一部分模板参数的类型可以通过调用时给的实参来推断;int main() {    // cout << Add<..., ..., double>(15, 17.8) << endl; // 错误,针对情况(1)指定返回值类型,无法跳过前两个类型    // cout << Add
(15, 17.8) << endl; // 正确,针对情况(1)指定返回值类型 // cout << Add
(15, 17.8) << endl; // 针对情况(2),V是第一个参数,从而不需要明确指定T、U的类型 // T、U的类型由实参自动推断得出}

}

【3】函数模板 -- 重载

#include

using namespace std;

#pragma warning(disable : 4996)namespace _nmsp1 {template

void myfunc(t tmpvalue) {cout << "myfunc(T tmpvalue)执行了" << endl;}template
void myfunc(t* tmpvalue) {cout << "myfunc(T* tmpvalue)执行了" << endl;}void myfunc(int tmpvalue) {cout << "myfunc(int tmpvalue)执行了" << endl;}}

// 函数模板重载int main() {_nmsp1::myfunc(12); // 调用 void myfunc(int tmpvalue)char* p = nullptr; _nmsp1::myfunc(p); // 调用 void myfunc(T* tmpvalue)_nmsp1::myfunc(12.1); // 调用 void myfunc(T tmpvalue)}

【4】函数模板 -- 特化

#include

using namespace std;

#pragma warning(disable : 4996)namespace _nmsp2 {// 泛化版本template <typename t, typename u>void tfunc(t& tmprv, u& tmprv2) {cout << "tfunc泛化版本" << endl;cout << tmprv << endl;cout << tmprv2 << endl;}

// 全特化版本template <    typename t = int,    typename u = double>    void tfunc(int& tmprv, double& tmprv2) {        cout << "---------------begin------------" << endl;        cout << "tfunc
特化版本" << endl; cout << tmprv << endl; cout << tmprv2 << endl; cout << "---------------end------------" << endl; }// 重载函数void tfunc(int& tmprv, double& tmprv2) { cout << "---------------begin------------" << endl; cout << "tfunc普通函数" << endl; cout << "---------------end------------" << endl;}// 模板参数数量上的偏特化// 模板参数范围上的偏特化

}

int main() {const char* p = "I Love China!"; int i = 12; _nmsp2::tfunc(p, i); // 调用泛化版本int k = 12; double db = 15.8; _nmsp2::tfunc(k, db); // 调用普通函数const int k2 = 12; _nmsp2::tfunc(k2, db); // 调用偏特化版本double j = 18.5; _nmsp2::tfunc(j, i); // 调用偏特化版本}

【5】函数模板 -- 缺省参数

#include

#include
#include
#include
#include <boost/type_index.hpp>using namespace std;

#pragma warning(disable : 4996)namespace _nmsp1 {int mf(int tmp1, int tmp2) { return 1; }int mf2(int tmp1, int tmp2) { return 10; }

typedef int(*FunType)(int, int);template 
void testfunc(t i, t j, f funcpoint = mf) { cout << funcpoint(i, j) << endl; }template
void testfunc2(t m) { t tmpvalue = m; cout << tmpvalue << endl; }

}

int main() {_nmsp1::testfunc(15, 16); // 调用 testfunc(T i, T j, F funcpoint = mf)_nmsp1::testfunc(15, 16, _nmsp1::mf2); // 调用 testfunc(T i, T j, F funcpoint = mf2)_nmsp1::testfunc2(12); // 调用 testfunc2(U m)}

【6】函数模板 -- 非类型模板参数

#include

#include
#include
#include
#include <boost/type_index.hpp>using namespace std;

#pragma warning(disable : 4996)namespace _nmsp2 {template <typename t, typename u, int val = 100>auto Add(t tv1, u tv2) {return tv1 + tv2 + val;}

template 
void mft() { cout << "mft()执行了" << endl; }double g_d = 1.3;template
auto Add2() { return 100; }

}

int main() {_nmsp2::Add<float, float>(22.3f, 11.8f); // val取100_nmsp2::Add<float, float, 800>(22.3f, 11.8f); // val取800// int k = 1000; // cout << _nmsp2::Add<float, float, k>(22.3f, 11.8f) << endl; // 编译出错,k在编译时没有确定具体的值

_nmsp2::mft
; // 调用_nmsp2::Add2
(); // 调用

}

参考致谢本博客为博主学习笔记,同时参考了网上众博主的博文以及相关专业书籍,在此表示感谢,本文若存在不足之处,请批评指正。本文若存在不足之处,请批评指正。

【1】C++ 新经典【2】C++11/14 高级编程 Boost 程序库探秘

上一篇:【C/C++基础进阶系列】C/C++ 泛型 -- 类模板(一)
下一篇:【C/C++基础进阶系列】C/C++ 对象模型 -- 类基础知识总结(二)

发表评论

最新留言

感谢大佬
[***.8.128.20]2025年04月12日 12时53分29秒