【C/C++】template 入门到高阶简单大纲

发布于:2025-06-04 ⋅ 阅读:(26) ⋅ 点赞:(0)

template 入门到高阶简单大纲

C++ 模板(template)是 C++ 中一种非常强大的特性,允许编写泛型代码,即能够处理不同类型数据的代码。模板的应用范围从基本使用到高阶技巧都有,它是实现类型安全、代码复用、以及泛型编程的重要工具。

1. 基本使用场景

模板最基本的用途是编写通用的算法和数据结构,这样可以避免在不同类型上重复编写相似代码。

函数模板

函数模板使得一个函数可以接受不同类型的参数,并根据调用时传入的类型自动推导参数类型。

#include <iostream>
using namespace std;

template <typename T>
T add(T a, T b) {
    return a + b;
}

int main() {
    cout << add(2, 3) << endl;         // int 类型
    cout << add(2.5, 3.5) << endl;     // double 类型
}

这里,add 是一个模板函数,能够接受任何类型 T

类模板

类模板允许我们定义通用类,能够处理不同类型的数据。一个常见的例子是 std::vector

#include <iostream>
using namespace std;

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

int main() {
    Box<int> intBox(10);
    Box<double> doubleBox(3.14);
    cout << intBox.getValue() << endl;    // 10
    cout << doubleBox.getValue() << endl; // 3.14
}

2. 进阶使用场景

模板特化

模板特化(template specialization)允许我们为某个特定类型提供不同的实现。它可以是全特化或偏特化。

全特化

当某个类型的模板实现与其他类型有所不同时,我们可以进行全特化。

template <typename T>
class Box {
public:
    T value;
    Box(T v) : value(v) {}
    void print() { cout << "General type: " << value << endl; }
};

// 对 int 类型的全特化
template <>
class Box<int> {
public:
    int value;
    Box(int v) : value(v) {}
    void print() { cout << "Specialized for int: " << value << endl; }
};

int main() {
    Box<double> b1(3.14);
    Box<int> b2(42);

    b1.print();  // General type: 3.14
    b2.print();  // Specialized for int: 42
}

偏特化

偏特化是模板参数不完全匹配时的特化。通常用于泛型类、函数模板进行优化。

template <typename T, typename U>
class Pair {
    T first;
    U second;
public:
    Pair(T a, U b) : first(a), second(b) {}
};

// 对 U 为 int 类型的偏特化
template <typename T>
class Pair<T, int> {
    T first;
    int second;
public:
    Pair(T a, int b) : first(a), second(b) {}
    void print() { cout << "Pair: " << first << ", " << second << endl; }
};

int main() {
    Pair<double, int> p(3.14, 42);
    p.print();  // Pair: 3.14, 42
}

模板的 SFINAE(Substitution Failure Is Not An Error)

SFINAE 是 C++ 模板的一个重要特性。当某个模板实例化失败时,编译器不会报错,而是尝试其他合适的重载或特化。

#include <type_traits>
#include <iostream>

template <typename T>
typename std::enable_if<std::is_integral<T>::value, bool>::type
isEven(T val) {
    return val % 2 == 0;
}

int main() {
    std::cout << isEven(4) << std::endl;     // 输出 1 (true)
    // std::cout << isEven(3.14) << std::endl;  // 编译错误,不支持浮动类型
}

通过 std::enable_ifstd::is_integral,我们可以限制模板函数仅在某些类型下有效。

3. 高阶应用

类型萃取(Type Traits)

C++ 中的类型萃取允许我们在编译期获取类型的特征(如是否是指针、是否是整数等)。这使得模板编程更加灵活。

#include <type_traits>
#include <iostream>

template <typename T>
void printType(T value) {
    if (std::is_integral<T>::value)
        std::cout << "Integral type: " << value << std::endl;
    else if (std::is_floating_point<T>::value)
        std::cout << "Floating point type: " << value << std::endl;
}

int main() {
    printType(42);        // Integral type: 42
    printType(3.14);      // Floating point type: 3.14
}

模板元编程(Template Metaprogramming)

模板元编程是使用模板的递归特性进行编译期计算。它常用于优化代码,减少运行时开销。

例如,计算阶乘:

template <unsigned N>
struct Factorial {
    static const unsigned value = N * Factorial<N - 1>::value;
};

template <>
struct Factorial<0> {
    static const unsigned value = 1;
};

int main() {
    std::cout << Factorial<5>::value << std::endl;  // 输出 120
}

通过递归的方式,在编译期就计算出 5!

CRTP(Curiously Recurring Template Pattern)

CRTP 是一种常见的设计模式,通过继承模板类自身来实现编译期多态。它通常用于优化虚函数的调用,避免运行时开销。

template <typename T>
class Base {
public:
    void interface() {
        static_cast<T*>(this)->implementation();
    }
};

class Derived : public Base<Derived> {
public:
    void implementation() {
        std::cout << "Derived implementation!" << std::endl;
    }
};

int main() {
    Derived d;
    d.interface();  // 输出 "Derived implementation!"
}

通过 CRTP,我们能够利用静态多态在编译期做出决策,从而提高性能。

模板的实现与内存优化

在高级 C++ 编程中,模板也可与内存管理结合,用来优化性能。例如,std::vector 使用了 std::allocator 来管理内存。

你可以通过自定义分配器来优化特定场景的内存使用,减少内存碎片等问题。这样,你的模板类可以在不同的内存模型下表现得更加高效。

template <typename T>
class MyAllocator {
public:
    T* allocate(std::size_t n) {
        return static_cast<T*>(::operator new(n * sizeof(T)));
    }

    void deallocate(T* p, std::size_t n) {
        ::operator delete(p);
    }
};

总结

C++ 模板在从简单的函数模板到高级的模板元编程、类型萃取、CRTP 等方面都有广泛应用。模板不仅可以减少重复代码,还能为程序员提供在编译期优化性能的能力,是 C++ 中最强大的特性之一。


网站公告

今日签到

点亮在社区的每一天
去签到