C++模板惯用法

本文详细探讨了C++模板编程的各种惯用法,包括模板语法、实例化和特化、编译优化、堆栈分配、类型推导等。通过示例解释了如何利用模板实现高效的功能,如计算数组元素个数、使用隐式转换的显式函数、函数模板和类模板的结合使用,以及如何解决实例化导致的代码膨胀问题。同时,文章还介绍了CRTP循环模板模式、traits和policy策略等高级技巧,旨在提升C++模板编程的实践能力。
摘要由CSDN通过智能技术生成

关于 C++ 模板编程的惯用法,note-to-self + keynote + idiom case + cross-reference 式笔记

目录


模板语法^

称谓:函数模板 (function template) vs. 模板函数 (template function),或 类模板 (class template) vs. 模板类 (template class),见 [CPP TEMP] 7.1

两阶段编译 (two-phase lookup)、第一实例化点 (first point of instantiation),见 [CPP LANG] 13.2.5 [CPP TEMP] 2.1.2

实例化 (instantiation) 和特化(又译专门化)(specialization)、生成的特化 (generated specialization) vs. 显式的特化 (explicit specialization),见 [CPP LANG] 13.2.2, C.13.7 [CPP TEMP] 7.2

不完全实例化 (incomplete instantiation),见 [CPP LANG] 13.2.2 [MODERN CPP] 1.8

完全特化 (complete specialization)、部分特化(又译偏特化)(partial specialization),见 [CPP LANG] 13.5 [CPP TEMP] 3.3, 3.4

特化顺序:更特化 (more specialized)、更泛化 (more general)、原始模板 (primary template),见 [CPP LANG] 13.5.1 [CPP TEMP] 7.2

非类型模板参数,见 [CPP LANG] 13.2.3 [CPP TEMP] 4

函数模板和普通函数间的重载,见 [CPP LANG] 13.3.2 [CPP TEMP] 2.4

函数模板的参数推导 (argument deduction),见 [CPP LANG] 13.3.1, C.13.4 [CPP TEMP] 2.2, 11

默认模板参数,见 [CPP LANG] 13.4.1 [CPP TEMP] 3.5

成员模板 (member template),见 [CPP LANG] 13.6.2 [CPP TEMP] 5.3

模板作为模板参数 (template template parameter),见 [CPP LANG] C.13.3 [CPP TEMP] 5.4

typename 限定词 (typename qualifier),见 [CPP LANG] C.13.5 [CPP TEMP] 5.1 [EFFECT CPP] Item 42

template 限定词 (template qualifier),见 [CPP LANG] C.13.6 [CPP TEMP] 5.1

模板代码组织:包含模型 (inclusion model) vs. 分离模型 (separation model) 又称分别编译 (separate compile),见 [CPP LANG] 13.7 [CPP TEMP] 6.1, 6.3

显式实例化 (explicit instantiation),见 [CPP LANG] C.13.10 [CPP TEMP] 6.2

设计思维:运行时多态 (run-time polymorphism) vs. 编译时多态 (compile-time polymorphism) 又称参数化多态 (parametric polymorphism),见 [CPP LANG] 13.6.1 [EFFECT CPP] Item 41 [CPP TEMP] 14

模板惯用法示例^

堆栈上分配^

on-stack allocation 的 std 案例:tr1::array 模板

使用模板方法的不足之处是使用编译时确定的 buffer size,为了能在运行时动态调整 stack 内存分配数量,可借助 VC CRT 的 _alloca, _malloca 函数

示例:一个 printf 式的生成 std::string 的函数

[cpp]  view plain copy
  1. template <size_t BufSize, class CharT>  
  2. inline  
  3. std::basic_string<CharT> make_string(const CharT* format, ...)  
  4. {  
  5.     CharT buf[BufSize];  
  6.     va_list args;  
  7.   
  8.     va_start(args, format);  
  9.     // vsprintf 是函数模板, 其针对 char 特化调用 vsprintf_s, 针对 wchar_t 特化调用 vswprintf_s  
  10.     vsprintf(buf, BufSize, format, args);  
  11.     va_end(args);  
  12.   
  13.     // 注意: 返回时构造可让 VC 编译优化为只有一次 string ctor 调用, 没有额外 copy  
  14.     return std::basic_string<CharT>(buf);  
  15. }  
编译优化的开关^

bool 模板参数,或整数模板参数 + 阈值,避免重复代码时借助编译优化

示例:一个支持透明色的 32bit blit 函数

[cpp]  view plain copy
  1. template <bool UseMask>  
  2. void blit(int* dst, const int* src, int mask, size_t size)  
  3. {  
  4.     for (size_t i = 0; i < size; i++, dst++, src++) {  
  5.         if (!UseMask || *src != mask)  
  6.             *dst = *src;  
  7.     }  
  8. }  
推导数组元素个数^

可由参数推导求出数组的元素个数,要求必须是数组名,而非指向数组的指针或 new[] 数组

示例:VC CRT 的 _countof 计算数组的元素个数

[cpp]  view plain copy
  1. // 以 C++ 方式编译时, _countof 的定义如下  
  2. template <typename _CountofType, size_t _SizeOfArray>  
  3. char (*__countof_helper(UNALIGNED _CountofType (&_Array)[_SizeOfArray]))[_SizeOfArray];  
  4. #define _countof(_Array) (sizeof(*__countof_helper(_Array)) + 0)  

示例:多数 VC CRT buffer 操作函数都有 Secure Template Overloads 版本

[cpp]  view plain copy
  1. template <size_t size>  
  2. errno_t strcpy_s(char (&strDestination)[size], const char *strSource);  
推导常数^

示例:掩码常数 Mask<N>::Value

[cpp]  view plain copy
  1. #define _MASK_VAL(x)    (1 << x)  
  2. // 用于代替上面的宏  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值