输入关键词开始搜索

C++ 模板基础

函数模板

// 不用模板 → 写 N 个重载
int max(int a, int b) { return a > b ? a : b; }
double max(double a, double b) { return a > b ? a : b; }

// 用模板 → 一个搞定所有类型
template <typename T>
T max(T a, T b) {
    return a > b ? a : b;
}

auto r1 = max(3, 5);        // T = int
auto r2 = max(3.14, 2.71);  // T = double
auto r3 = max<float>(3, 5.0); // 显式指定 T = float

// 多个模板参数
template <typename T, typename U>
auto add(T a, U b) -> decltype(a + b) {   // C++11 后置返回类型
    return a + b;
}

// C++14 简化:auto 自动推导返回类型
template <typename T, typename U>
auto add(T a, U b) {
    return a + b;
}

类模板

template <typename T>
class Stack {
    vector<T> data;
public:
    void push(const T &val) { data.push_back(val); }
    T pop() {
        T val = data.back();
        data.pop_back();
        return val;
    }
    bool empty() const { return data.empty(); }
};

Stack<int> intStack;
Stack<string> strStack;

非类型模板参数

// 编译期固定大小的数组
template <typename T, size_t N>
class Array {
    T data[N];
public:
    T &operator[](size_t i) { return data[i]; }
    size_t size() const { return N; }
};

Array<int, 10> arr;    // 10 个 int,栈上分配
Array<double, 5> arr2; // 5 个 double

模板特化

// 通用模板
template <typename T>
class Traits {
public:
    static const char *name() { return "unknown"; }
};

// 全特化
template <>
class Traits<int> {
public:
    static const char *name() { return "int"; }
};

template <>
class Traits<double> {
public:
    static const char *name() { return "double"; }
};

cout << Traits<int>::name();    // "int"
cout << Traits<float>::name();  // "unknown" (走通用模板)

SFINAE 入门

Substitution Failure Is Not An Error — 替换失败不是错误。

// 仅在 T 有 .size() 方法时启用
template <typename T>
auto getSize(const T &t) -> decltype(t.size()) {
    return t.size();
}

// C++20 Concept 替代方案(更可读)
// template <typename T>
//     requires requires(T t) { t.size(); }
// auto getSize(const T &t) { return t.size(); }

常见陷阱

// ❌ 模板定义放在 .cpp → 链接错误
// ✅ 模板定义必须放在头文件(或显式实例化)

// ❌ 忘记 typename
template <typename T>
void foo() {
    typename T::value_type x;  // 告诉编译器 T::value_type 是类型
}

// ❌ 模板递归太深 → 编译超时
// ✅ 考虑用折叠表达式(C++17)替代递归