7. 模板和泛型编程

函数模板

1. 基本语法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// 简单的函数模板
template<typename T>
T max(T a, T b) {
    return (a > b) ? a : b;
}

// 使用示例
int i = max(10, 20);         // T 为 int
double d = max(3.14, 2.72);  // T 为 double
std::string s = max("hello"s, "world"s);  // T 为 string

// 多个模板参数
template<typename T, typename U>
auto add(T a, U b) -> decltype(a + b) {
    return a + b;
}

// 使用示例
auto result = add(10, 3.14);  // 返回类型为double

2. 模板参数推导

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
// 自动推导
template<typename T>
void print(T value) {
    std::cout << value << "\n";
}

print(42);      // T 推导为 int
print("hello"); // T 推导为 const char*

// 显式指定类型
print<double>(42);  // T 为 double

// 推导指引(C++17)
template<typename T>
class Container {
    T value;
public:
    Container(T val) : value(val) {}
};

Container container{42};  // 自动推导为Container<int>

3. 非类型模板参数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 使用非类型参数
template<typename T, size_t N>
class Array {
    T data[N];
public:
    constexpr size_t size() const { return N; }
    T& operator[](size_t i) { return data[i]; }
};

// 使用示例
Array<int, 5> arr;  // 固定大小的数组
static_assert(arr.size() == 5);

// 非类型参数作为常量
template<int Base>
int power(int exp) {
    int result = 1;
    for(int i = 0; i < exp; ++i) {
        result *= Base;
    }
    return result;
}

int value = power<2>(3);  // 计算2的3次方

类模板

1. 基本定义

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 简单的类模板
template<typename T>
class Box {
private:
    T content;
    
public:
    Box(T value) : content(value) {}
    T get() const { return content; }
    void set(T value) { content = value; }
};

// 使用示例
Box<int> intBox(42);
Box<std::string> strBox("Hello");

// 多个模板参数
template<typename K, typename V>
class Pair {
    K key;
    V value;
public:
    Pair(const K& k, const V& v) : key(k), value(v) {}
    K getKey() const { return key; }
    V getValue() const { return value; }
};

2. 成员函数模板

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
template<typename T>
class Container {
public:
    // 成员函数模板
    template<typename U>
    void copyFrom(const Container<U>& other) {
        // 从其他类型容器复制
    }
    
    // 构造函数模板
    template<typename U>
    Container(const Container<U>& other) {
        copyFrom(other);
    }
};

// 使用示例
Container<double> doubleContainer;
Container<int> intContainer(doubleContainer);  // 隐式转换

3. 模板特化

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 主模板
template<typename T>
class SmartPtr {
    T* ptr;
public:
    SmartPtr(T* p) : ptr(p) {}
    ~SmartPtr() { delete ptr; }
    T& operator*() { return *ptr; }
};

// 完全特化
template<>
class SmartPtr<void> {
    void* ptr;
public:
    SmartPtr(void* p) : ptr(p) {}
    ~SmartPtr() { free(ptr); }
};

// 偏特化
template<typename T>
class SmartPtr<T[]> {
    T* ptr;
public:
    SmartPtr(T* p) : ptr(p) {}
    ~SmartPtr() { delete[] ptr; }
    T& operator[](size_t i) { return ptr[i]; }
};

变参模板

1. 基础用法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
// 变参函数模板
template<typename... Args>
void printAll(Args... args) {
    (std::cout << ... << args) << "\n";  // 折叠表达式(C++17)
}

// 使用示例
printAll(1, "hello", 3.14);  // 打印:1hello3.14

// 递归方式展开参数包
template<typename T>
void print(T value) {
    std::cout << value << "\n";
}

template<typename T, typename... Args>
void print(T first, Args... rest) {
    std::cout << first << ", ";
    print(rest...);
}

2. 折叠表达式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// 使用折叠表达式(C++17)
template<typename... Args>
auto sum(Args... args) {
    return (... + args);  // 一元左折叠
}

template<typename... Args>
bool allTrue(Args... args) {
    return (... && args);  // 一元左折叠
}

// 带初始值的折叠
template<typename... Args>
auto sumWithInit(Args... args) {
    return (0 + ... + args);  // 二元左折叠
}

3. 变参类模板

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// 变参类模板
template<typename... Types>
class Tuple;

// 特化为空
template<>
class Tuple<> {};

// 递归特化
template<typename Head, typename... Tail>
class Tuple<Head, Tail...> : private Tuple<Tail...> {
    Head head;
public:
    Tuple(Head h, Tail... tail)
        : Tuple<Tail...>(tail...), head(h) {}
    
    Head getHead() const { return head; }
};

模板元编程

1. 编译期计算

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 编译期阶乘计算
template<unsigned N>
struct Factorial {
    static constexpr unsigned value = N * Factorial<N-1>::value;
};

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

// 使用示例
constexpr auto fact5 = Factorial<5>::value;  // 120

// 编译期if
template<bool Condition, typename T, typename U>
struct Conditional {
    using type = T;
};

template<typename T, typename U>
struct Conditional<false, T, U> {
    using type = U;
};

2. 类型特征

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 自定义类型特征
template<typename T>
struct IsPointer {
    static constexpr bool value = false;
};

template<typename T>
struct IsPointer<T*> {
    static constexpr bool value = true;
};

// 使用示例
static_assert(IsPointer<int*>::value);
static_assert(!IsPointer<int>::value);

// 类型变换
template<typename T>
struct RemovePointer {
    using type = T;
};

template<typename T>
struct RemovePointer<T*> {
    using type = T;
};

3. SFINAE和概念

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
// SFINAE示例
template<typename T>
typename std::enable_if<std::is_integral<T>::value, bool>::type
isEven(T t) {
    return t % 2 == 0;
}

// 使用概念(C++20)
template<typename T>
concept Numeric = std::is_arithmetic_v<T>;

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

// 复合概念
template<typename T>
concept Sortable = requires(T& a, T& b) {
    { a < b } -> std::convertible_to<bool>;
    std::swap(a, b);
};

4. 元函数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 类型计算
template<typename T>
struct AddConst {
    using type = const T;
};

// 值计算
template<typename T>
struct TypeSize {
    static constexpr size_t value = sizeof(T);
};

// 条件元编程
template<typename T>
struct IsLargeType {
    static constexpr bool value = sizeof(T) > 8;
};

// 使用示例
using ConstInt = typename AddConst<int>::type;
constexpr size_t intSize = TypeSize<int>::value;
constexpr bool isLarge = IsLargeType<std::string>::value;

57.12k 字
43篇文章