C++模板进阶:从入门到精通

C++ 模板快速学习:从基础到高级

作者:暴走的小蜗牛
时间:2025年7月1日
标签:C++模板、泛型编程、元编程、CRTP、SFINAE、Concepts、模板元函数


一、编写目标

C++ 模板是其最强大也是最复杂的语法功能之一,元编程、类型推导、类型演算、静态多态都基于模板技术实现。这篇博客从基础到高级全面分析 C++ 模板,给出一条可行的学习途径。


二、模板学习路线图

以下是基于简单→复杂→元编程→ C++20 的模板技术进阶途径:

模板基础
函数模板
类模板
模板特化
SFINAE 与 enable_if
类型萌取 traits
模板元编程 TMP
C++20 Concepts
CRTP 模式
高级设计实践

三、基础语法结构

3.1 函数模板

template<typename T>
T add(T a, T b) {
    return a + b;
}
  • typename 可以用 class
  • T 为类型参数,在函数使用
  • 类似于 macro 编程,但安全性更好

3.2 类模板

template<typename T>
class Box {
public:
    Box(T val) : value(val) {}
    T get() const { return value; }
private:
    T value;
};

展示:

Box<int> intBox(42);
Box<std::string> strBox("hello");

四、模板特化与偏特化

4.1 全特化

template<>
class Box<int> {
public:
    Box(int v) : value(v * 10) {}
    int get() const { return value; }
private:
    int value;
};

4.2 偏特化

template<typename T, typename U>
class Pair {};

template<typename T>
class Pair<T, int> {
    // U 特化为 int 时特化行为
};

五、SFINAE 与 enable_if 编译期类型选择

5.1 基础示例

template<typename T>
typename std::enable_if<std::is_integral<T>::value, T>::type
safe_add(T a, T b) {
    return a + b;
}

5.2 分析

  • enable_if<condition, type> 在 condition=false 时以编译失败选择后处理
  • 在组合 overload 时很有效

5.3 应用: 分类处理

template<typename T>
typename std::enable_if<std::is_floating_point<T>::value>::type
print(T v) { std::cout << "float: " << v << std::endl; }

template<typename T>
typename std::enable_if<std::is_integral<T>::value>::type
print(T v) { std::cout << "int: " << v << std::endl; }

六、类型 traits 技术

6.1 常规示例

if constexpr (std::is_pointer<T>::value) {
   // 按照指针处理
} else {
   // 普通值
}

6.2 自定义 traits

template<typename T>
struct is_vector : std::false_type {};

template<typename T, typename A>
struct is_vector<std::vector<T, A>> : std::true_type {};

七、C++20 Concepts

7.1 概念

#include <concepts>

template<typename T>
requires std::integral<T>
T half(T x) {
    return x / 2;
}

7.2 自定义 Concept

template<typename T>
concept Addable = requires(T a, T b) {
    { a + b } -> std::convertible_to<T>;
};

八、模板元编程 TMP

8.1 递归 Fibonacci

template<int N>
struct Fib {
    static constexpr int value = Fib<N-1>::value + Fib<N-2>::value;
};

template<> struct Fib<1> { static constexpr int value = 1; };
template<> struct Fib<0> { static constexpr int value = 0; };

static_assert(Fib<5>::value == 5);

8.2 编译期 if

template<typename T>
void check() {
    if constexpr (std::is_same<T, int>::value) {
        std::cout << "int";
    } else {
        std::cout << "other";
    }
}

九、CRTP 奇异递归模板模式

9.1 基本模式

template<typename Derived>
class Counter {
public:
    Counter() { ++count; }
    static int count;
};

template<typename D>
int Counter<D>::count = 0;

class My : public Counter<My> {};

9.2 应用场景

  • 静态多态
  • 防止虚函数调用差怪
  • 性能提升

十、实战:构建泛型算法库

10.1 sort_if 功能

template<typename T>
concept LessThanComparable = requires(T a, T b) {
    { a < b } -> std::convertible_to<bool>;
};

template<typename T>
requires LessThanComparable<T>
void sort_if(std::vector<T>& vec) {
    std::sort(vec.begin(), vec.end());
}

10.2 高级组合:综合 traits + CRTP + Concepts 构建编译期选择算法


十一、常见问题与解决方案

问题原因解決策略
错误信息复杂模板嵌套分阻类型 + static_assert
可读性差enable_if 突出使用 Concepts
编译慢TMP 递归过深限制递归
过度抽象CRTP 过深简单化设计

十二、结论与学习建议

  • 模板技术是环环相扩的
  • 前期重培基础,后期重经验

推荐学习步骤

  1. 熟悉基础函数、类模板语法
  2. 理解特化、enable_if编译选择
  3. 精通类型萌取 traits
  4. 逐步入手 TMP 与 CRTP
  5. 体验 Concepts 应用

附录

  • C++ Templates: The Complete Guide 2nd Edition
  • Effective Modern C++ - Scott Meyers
  • https://en.cppreference.com
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值