一个模板元编程示例
代码
#include <iostream>
#include <type_traits>// 基础模板定义
template <bool AddOrRemoveRef> struct Fun_;// 偏特化:添加左值引用
template <>
struct Fun_<true>{template <typename T>using type = typename std::add_lvalue_reference<T>::type;
};// 偏特化:移除引用
template <>
struct Fun_<false> {template<typename T>using type = typename std::remove_reference<T>::type;
};// 正确的模板别名定义
template <bool AddOrRemove, typename T>
using Fun = typename Fun_<AddOrRemove>::template type<T>;// 正确的Res_定义
template <typename T>
using Res_ = Fun<false, T>;int main() {// 测试Res_<int&> h = 3; // h的类型是intstd::cout << h << std::endl;return 0;
}
这段代码展示了使用模板元编程技术实现的条件类型转换,根据布尔值参数决定添加左值引用或移除引用。下面逐步解析其工作原理:
1. 基础模板声明
template <bool AddOrRemoveRef> struct Fun_;
-
声明主模板
Fun_
,接受一个布尔值非类型参数AddOrRemoveRef
-
作用:作为分发开关,根据布尔值选择不同特化版本
2. 特化版本实现
(1) true
特化:添加左值引用
template <>
struct Fun_<true> {template <typename T>using type = typename std::add_lvalue_reference<T>::type;
};
-
当
AddOrRemoveRef=true
时激活 -
使用
std::add_lvalue_reference
将任意类型T
转换为左值引用类型T&
-
示例:
int → int&
(2) false
特化:移除引用
template <>
struct Fun_<false> {template<typename T>using type = typename std::remove_reference<T>::type;
};
-
当
AddOrRemoveRef=false
时激活 -
使用
std::remove_reference
移除类型的所有引用修饰 -
示例:
int& → int
,int&& → int
3. 统一接口封装
template <bool AddOrRemove, typename T>
using Fun = typename Fun_<AddOrRemove>::template type<T>;
-
创建别名模板
Fun
简化调用 -
关键语法:
-
typename
:指明Fun_<AddOrRemove>::type
是依赖类型名 -
template
:指明type
是依赖模板名
-
-
调用方式:
Fun<flag, T>
根据flag选择转换操作
4. 特定功能封装
template <typename T>
using Res_ = Fun<false, T>;
-
固定
false
参数的便捷别名 -
专用功能:移除任何传入类型的引用
-
等价于:
Res_<T> = std::remove_reference_t<T>
5. 测试代码分析
Res_<int&> h = 3; // 等价于 int h = 3
-
Res_<int&>
实例化过程:-
通过
Res_
调用Fun<false, int&>
-
激活
Fun_<false>::type<int&>
-
执行
std::remove_reference<int&>::type
→int
-
-
变量
h
实际类型为int
-
赋值
3
符合整型要求
设计模式总结
组件 | 作用 | 示例输入→输出 |
---|---|---|
Fun_<true> | 添加左值引用 | int → int& |
Fun_<false> | 移除所有引用 | const int& → const int |
Res_ | 专用移除引用工具 | double&& → double |
关键语法解析
using Fun = typename Fun_<B>::template type<T>;
// 1. typename → 声明后面是类型(依赖名称解析)
// 2. template → 表明type是模板(防止编译器误解析)
// 3. ::type → 访问嵌套类型
典型应用场景
-
通用类型处理框架中条件转换
-
元函数转发时减少
::type
重复书写 -
构建复杂类型运算的中间层
这种设计模式在标准库元编程中常见(如std::conditional
的实现),通过布尔开关分发处理逻辑,提高模板代码的复用性和可读性。