🧠 C++ 泛型编程


📚 一、什么是泛型编程?

泛型编程(Generic Programming) 是一种以类型无关的方式编写程序的技术,它允许我们写出适用于多种数据类型的通用代码。

在 C++ 中,模板(Template) 是实现泛型编程的核心机制。通过模板,我们可以为函数和类定义“蓝图”,编译器会根据实际使用的类型自动生成对应的代码。


🧩 二、为什么需要泛型编程?

✅ 优点:

  • 代码复用:一个函数或类可以处理多个类型。
  • 类型安全:编译时检查类型,避免运行时错误。
  • 性能优化:模板生成的代码是静态绑定的,几乎无额外开销。

❌ 没有泛型的情况:

int maxInt(int a, int b) {
    return (a > b) ? a : b;
}

double maxDouble(double a, double b) {
    return (a > b) ? a : b;
}

如果支持 floatlong long 等,就需要写很多重复代码。这时候就要引入泛型!


🔁 三、函数模板 Function Template

✅ 基本语法:

template <typename T>
T max(T a, T b) {
    return (a > b) ? a : b;
}
  • template <typename T>:声明这是一个模板函数,T 是类型占位符。
  • 使用时无需指定类型,编译器自动推导。

💻 示例使用:

int main() {
    std::cout << max(3, 5) << "\n";       // T -> int
    std::cout << max(3.14, 2.718) << "\n";// T -> double
    std::cout << max('A', 'B') << "\n";   // T -> char
    return 0;
}

🧱 四、类模板 Class Template

当我们希望一个类能处理不同类型的数据时,就可以使用类模板。

✅ 示例:通用栈类

template <typename T>
class Stack {
private:
    std::vector<T> elements;
public:
    void push(const T& value) { elements.push_back(value); }
    void pop()                { elements.pop_back(); }
    const T& top() const      { return elements.back(); }
    bool empty() const        { return elements.empty(); }
};

💻 使用示例:

int main() {
    Stack<int> intStack;
    intStack.push(1);
    intStack.push(2);
    std::cout << "Top: " << intStack.top() << "\n";

    Stack<std::string> stringStack;
    stringStack.push("Hello");
    stringStack.push("World");
    std::cout << "Top: " << stringStack.top() << "\n";
}

🧬 五、多参数模板 Multiple Template Parameters

你可以为模板指定多个类型参数:

template <typename Key, typename Value>
class Pair {
private:
    Key key;
    Value value;
public:
    Pair(Key k, Value v) : key(k), value(v) {}
    void print() const {
        std::cout << "[" << key << " : " << value << "]\n";
    }
};

💻 使用:

Pair<std::string, int> p("Age", 25);
p.print();  // 输出 [Age : 25]

⚙️ 六、默认模板参数 Default Template Arguments

你可以在模板中为类型设置默认值:

template <typename T = int>
class Box {
private:
    T data;
public:
    Box(T d) : data(d) {}
    void show() const { std::cout << data << "\n"; }
};

💻 使用:

Box<> box1(100);         // 默认 int
Box<double> box2(3.14);  // 显式 double

🧮 七、非类型模板参数 Non-type Template Parameters

除了类型,还可以传递常量值作为模板参数:

template <int N>
class Array {
private:
    int data[N];
public:
    void fill(int val) {
        for (int i = 0; i < N; ++i)
            data[i] = val;
    }

    void print() const {
        for (int i = 0; i < N; ++i)
            std::cout << data[i] << " ";
        std::cout << "\n";
    }
};

💻 使用:

Array<5> arr;
arr.fill(10);
arr.print();  // 输出 10 10 10 10 10

🔄 八、模板特化 Template Specialization

有时我们需要为特定类型提供不同的实现,这就是模板特化

✅ 部分特化 Partial Specialization(仅限类模板)

template <typename T>
class Container {
public:
    void info() { std::cout << "General container\n"; }
};

// 特化指针类型
template <typename T>
class Container<T*> {
public:
    void info() { std::cout << "Pointer container\n"; }
};

💻 使用:

Container<int> c1;
c1.info();  // General container

Container<int*> c2;
c2.info();  // Pointer container

🎯 九、STL 中的泛型应用(标准库)

C++ 标准库大量使用了泛型编程,例如:

容器 描述
std::vector<T> 动态数组
std::map<K,V> 键值对容器
std::list<T> 双向链表
std::set<T> 不可重复元素集合

这些容器都使用了模板技术,使得它们可以适应任意类型。


🧪 十、实战练习题

✅ 练习 1:编写一个通用交换函数

template <typename T>
void swapValues(T& a, T& b) {
    T temp = a;
    a = b;
    b = temp;
}

✅ 练习 2:实现一个通用排序算法(冒泡排序)

template <typename T>
void bubbleSort(T arr[], int size) {
    for (int i = 0; i < size - 1; ++i)
        for (int j = 0; j < size - i - 1; ++j)
            if (arr[j] > arr[j + 1])
                std::swap(arr[j], arr[j + 1]);
}

🧠 十一、常见误区与注意事项

问题 解决方法
编译错误提示太长 多看模板实例化后的代码
类型不匹配 确保传入类型支持操作符
模板不能分离 .h.cpp 模板实现必须放在头文件中
函数模板无法重载 可以通过偏特化或 SFINAE 技术解决

📈 十二、高级主题(进阶)

  1. SFINAE(Substitution Failure Is Not An Error)
  2. Concepts(C++20)
  3. 模板元编程 TMP(Template Metaprogramming)
  4. Policy-based 设计模式

📘 总结

主题 内容
泛型编程 用模板编写类型无关的代码
函数模板 支持通用函数
类模板 支持通用类
特化与偏特化 为特定类型定制行为
STL 应用 vector、map、set 等
高级技巧 Concepts、SFINAE、TMP

📚 推荐学习资源

  • 📖《C++ Primer》第五版
  • 📖《Effective Modern C++》Scott Meyers
  • 📘 cppreference.com(权威文档)
  • 🧪 LeetCode / HackerRank 上练习模板题目

🎉 恭喜你完成了本教程!现在你可以编写自己的泛型库啦!

3 条评论

  • @ 2025-6-2 20:44:33
    #include<iostream>
    using namespace std;
    template <int N>
    struct Array {
    private:
    	int data[N];
    public:
    	void fill(int val) {
    		for (int i = 0; i < N; ++i)
    			data[i] = val;
    	}
    	
    	void print() const {
    		for (int i = 0; i < N; ++i)
    			cout << data[i] << " ";
    		cout << "\n";
    	}
    };
    
    int main() {
    	Array<5> arr;
    	arr.fill(10);
    	arr.print();  // 输出 10 10 10 10 10
    	
    	return 0;
    }
    
    • @ 2025-6-2 20:35:02
      #include<iostream>
      #include<vector>
      using namespace std;
      template <typename T>
      struct Stack {
      //public:
      	void push(const T& value) {
      		elements.push_back(value);
      	}
      	void pop()                {
      		elements.pop_back();
      	}
      	const T& top() const      {
      		return elements.back();
      	}
      	bool empty() const        {
      		return elements.empty();
      	}
      private:
      	vector<T> elements;
      
      };
      
      int main() {
      	Stack<int> t;
      	int n;
      	cin >> n;
      	while(n!=0){
      		t.push(n%8);
      		n/=8;
      	}
      	while(!t.empty()){
      		cout<<t.top();
      		t.pop();
      	}
      	return 0;
      }
      

      在C++中,const 是一个类型修饰符,用于表示“常量”或“不可修改”。在你提供的代码中,const 出现在几个不同的上下文中,每个都有特定的含义:

      1. 成员函数后的 const

      const T& top() const;
      bool empty() const;
      

      这里的 const 表示这些成员函数是“常量成员函数”,即它们承诺不会修改对象的状态。具体来说:

      • const T& top() const:返回栈顶元素的常量引用(防止修改栈顶元素),并且函数本身不会修改对象
      • bool empty() const:检查栈是否为空,同样不会修改对象

      2. 参数列表中的 const

      void push(const T& value);
      

      这里的 const T& 表示参数 value 是一个常量引用

      • 函数内部不能修改 value 的值。
      • 使用引用避免了对象的拷贝,提高效率。

      3. 返回类型中的 const

      const T& top() const;
      

      返回值是一个 const T&,即常量引用

      • 调用者不能通过返回的引用修改栈顶元素。
      • 例如:t.top() = 10; 会导致编译错误。

      为什么需要这些 const

      • 安全性:防止意外修改对象状态或传入的参数。
      • 兼容性:常量对象(如 const Stack<int> s;)只能调用 const 成员函数。
      • 良好的设计:明确函数的副作用,提高代码可读性。

      示例说明

      在你的代码中:

      Stack<int> t;
      // ...
      const T& top() const { return elements.back(); }
      
      • top() 返回的是 const int&,防止你直接修改栈顶元素。
      • 如果没有这个 const,你可以写 t.top() = 10;,这会破坏栈的封装性(栈顶元素应该只能通过 pushpop 修改)。

      总结:const 在C++中用于确保数据的不可变性,是一种重要的类型安全机制。

      • @ 2025-5-30 8:11:41

        C++ 泛型编程完整教程

        一、泛型编程概述

        1.1 什么是泛型编程?

        泛型编程(Generic Programming)是一种编程范式,它允许编写不依赖于具体数据类型的代码。通过泛型编程,我们可以创建通用的算法和数据结构,这些算法和数据结构能够处理多种数据类型,而不需要为每种数据类型单独编写代码。

        1.2 为什么需要泛型编程?

        • 代码复用:避免为不同数据类型重复编写相似的代码
        • 类型安全:在编译时进行类型检查,减少运行时错误
        • 性能优化:通过模板实例化生成针对特定类型的高效代码

        1.3 C++ 中的泛型编程实现方式

        C++ 主要通过以下两种方式实现泛型编程:

        1. 模板(Templates):函数模板和类模板
        2. 标准模板库(STL):包含容器、算法、迭代器等泛型组件

        二、函数模板

        2.1 函数模板的定义与使用

        函数模板允许创建一个通用的函数,能够处理多种数据类型。

        #include <iostream>
        using namespace std;
        
        // 函数模板:交换两个变量的值
        template <typename T>
        void swap(T& a, T& b) {
            T temp = a;
            a = b;
            b = temp;
        }
        
        int main() {
            // 交换整数
            int x = 10, y = 20;
            cout << "Before swap: x = " << x << ", y = " << y << endl;
            swap(x, y); // 自动推导类型为int
            cout << "After swap: x = " << x << ", y = " << y << endl;
        
            // 交换浮点数
            double a = 3.14, b = 2.71;
            cout << "\nBefore swap: a = " << a << ", b = " << b << endl;
            swap(a, b); // 自动推导类型为double
            cout << "After swap: a = " << a << ", b = " << b << endl;
        
            // 显式指定模板参数类型
            string s1 = "Hello", s2 = "World";
            cout << "\nBefore swap: s1 = " << s1 << ", s2 = " << s2 << endl;
            swap<string>(s1, s2); // 显式指定类型为string
            cout << "After swap: s1 = " << s1 << ", s2 = " << s2 << endl;
        
            return 0;
        }
        

        2.2 函数模板的重载

        函数模板可以像普通函数一样被重载。

        #include <iostream>
        using namespace std;
        
        // 函数模板:返回两个值中的较大值
        template <typename T>
        T max(T a, T b) {
            return (a > b) ? a : b;
        }
        
        // 重载函数模板:处理C风格字符串
        const char* max(const char* a, const char* b) {
            return (strcmp(a, b) > 0) ? a : b;
        }
        
        int main() {
            int x = 10, y = 20;
            cout << "Max of " << x << " and " << y << " is " << max(x, y) << endl;
        
            double a = 3.14, b = 2.71;
            cout << "Max of " << a << " and " << b << " is " << max(a, b) << endl;
        
            const char* s1 = "apple";
            const char* s2 = "banana";
            cout << "Max of " << s1 << " and " << s2 << " is " << max(s1, s2) << endl;
        
            return 0;
        }
        

        2.3 多模板参数的函数模板

        函数模板可以有多个模板参数。

        #include <iostream>
        using namespace std;
        
        // 多模板参数的函数模板
        template <typename T, typename U>
        T convert(U value) {
            return static_cast<T>(value);
        }
        
        int main() {
            double d = 3.14;
            int i = convert<int>(d); // 显式指定目标类型
            cout << "Converted " << d << " to " << i << endl;
        
            float f = 2.71f;
            long l = convert<long, float>(f); // 显式指定两个模板参数
            cout << "Converted " << f << " to " << l << endl;
        
            return 0;
        }
        

        三、类模板

        3.1 类模板的定义与使用

        类模板允许创建通用的类,能够处理多种数据类型。

        #include <iostream>
        using namespace std;
        
        // 类模板:动态数组
        template <typename T>
        class Array {
        private:
            T* data;      // 指向数组的指针
            int size;     // 当前元素个数
            int capacity; // 数组容量
        
            // 扩容函数
            void resize(int newCapacity) {
                T* newData = new T[newCapacity];
                for (int i = 0; i < size; i++) {
                    newData[i] = data[i];
                }
                delete[] data;
                data = newData;
                capacity = newCapacity;
            }
        
        public:
            // 构造函数
            Array(int initialCapacity = 10) : size(0), capacity(initialCapacity) {
                data = new T[capacity];
            }
        
            // 析构函数
            ~Array() {
                delete[] data;
            }
        
            // 获取元素个数
            int getSize() const {
                return size;
            }
        
            // 获取容量
            int getCapacity() const {
                return capacity;
            }
        
            // 判断数组是否为空
            bool isEmpty() const {
                return size == 0;
            }
        
            // 在末尾添加元素
            void add(T element) {
                if (size == capacity) {
                    resize(2 * capacity);
                }
                data[size++] = element;
            }
        
            // 获取指定位置的元素
            T get(int index) const {
                if (index < 0 || index >= size) {
                    throw out_of_range("Index out of range");
                }
                return data[index];
            }
        
            // 设置指定位置的元素值
            void set(int index, T value) {
                if (index < 0 || index >= size) {
                    throw out_of_range("Index out of range");
                }
                data[index] = value;
            }
        
            // 打印数组内容
            void print() const {
                cout << "Array: size = " << size << ", capacity = " << capacity << endl;
                cout << "[";
                for (int i = 0; i < size; i++) {
                    cout << data[i];
                    if (i != size - 1) {
                        cout << ", ";
                    }
                }
                cout << "]" << endl;
            }
        };
        
        int main() {
            // 创建存储整数的数组
            Array<int> intArray;
            for (int i = 0; i < 5; i++) {
                intArray.add(i);
            }
            cout << "Integer Array:" << endl;
            intArray.print();
        
            // 创建存储字符串的数组
            Array<string> stringArray;
            stringArray.add("Hello");
            stringArray.add("World");
            cout << "\nString Array:" << endl;
            stringArray.print();
        
            return 0;
        }
        

        3.2 类模板的特化

        当模板处理特定类型时,可能需要特殊的实现。这时可以使用类模板特化。

        #include <iostream>
        #include <cstring>
        using namespace std;
        
        // 通用类模板
        template <typename T>
        class Storage {
        private:
            T data;
        
        public:
            Storage(const T& value) : data(value) {
                cout << "Generic Storage constructor" << endl;
            }
        
            void print() const {
                cout << "Stored value: " << data << endl;
            }
        };
        
        // 类模板特化:针对char*类型
        template <>
        class Storage<char*> {
        private:
            char* data;
        
        public:
            Storage(const char* value) {
                cout << "Specialized Storage constructor for char*" << endl;
                if (value == nullptr) {
                    data = nullptr;
                } else {
                    // 为字符串分配内存并复制内容
                    data = new char[strlen(value) + 1];
                    strcpy(data, value);
                }
            }
        
            ~Storage() {
                delete[] data;
            }
        
            void print() const {
                cout << "Stored string: " << (data ? data : "null") << endl;
            }
        };
        
        int main() {
            // 使用通用模板
            Storage<int> intStorage(42);
            intStorage.print();
        
            // 使用特化模板
            Storage<char*> strStorage("Hello, World!");
            strStorage.print();
        
            return 0;
        }
        

        3.3 类模板的部分特化

        C++ 允许对类模板进行部分特化,即只特化部分模板参数。

        #include <iostream>
        using namespace std;
        
        // 通用类模板
        template <typename T, typename U>
        class Pair {
        public:
            Pair(const T& first, const U& second) : first(first), second(second) {
                cout << "Generic Pair constructor" << endl;
            }
        
            void print() const {
                cout << "First: " << first << ", Second: " << second << endl;
            }
        
        private:
            T first;
            U second;
        };
        
        // 部分特化:当T和U相同时
        template <typename T>
        class Pair<T, T> {
        public:
            Pair(const T& first, const T& second) : first(first), second(second) {
                cout << "Partial specialized Pair constructor (same types)" << endl;
            }
        
            void print() const {
                cout << "First and Second (same type): " << first << ", " << second << endl;
            }
        
        private:
            T first;
            T second;
        };
        
        // 部分特化:当U为int时
        template <typename T>
        class Pair<T, int> {
        public:
            Pair(const T& first, const int& second) : first(first), second(second) {
                cout << "Partial specialized Pair constructor (U is int)" << endl;
            }
        
            void print() const {
                cout << "First: " << first << ", Second (int): " << second << endl;
            }
        
        private:
            T first;
            int second;
        };
        
        int main() {
            // 使用通用模板
            Pair<double, string> p1(3.14, "Hello");
            p1.print();
        
            // 使用相同类型的部分特化
            Pair<int, int> p2(10, 20);
            p2.print();
        
            // 使用U为int的部分特化
            Pair<string, int> p3("World", 42);
            p3.print();
        
            return 0;
        }
        

        四、标准模板库(STL)

        4.1 STL 概述

        STL 是 C++ 标准库的重要组成部分,提供了一系列通用的模板类和函数,包括容器、算法、迭代器、函数对象等。

        STL 的主要组件:

        • 容器(Containers):用于存储数据的类模板
        • 算法(Algorithms):操作容器中数据的函数模板
        • 迭代器(Iterators):提供访问容器中元素的方法
        • 函数对象(Function Objects):重载了函数调用运算符的类
        • 适配器(Adapters):修改其他组件接口的组件
        • 分配器(Allocators):负责内存分配和释放的组件

        4.2 容器

        STL 提供了多种容器,分为顺序容器、关联容器和容器适配器。

        4.2.1 顺序容器

        顺序容器按线性顺序存储元素。

        #include <iostream>
        #include <vector>
        #include <list>
        #include <deque>
        using namespace std;
        
        int main() {
            // vector:动态数组
            vector<int> vec;
            vec.push_back(10);
            vec.push_back(20);
            vec.push_back(30);
            cout << "Vector: ";
            for (int i : vec) {
                cout << i << " ";
            }
            cout << endl;
        
            // list:双向链表
            list<string> lst;
            lst.push_back("apple");
            lst.push_front("banana");
            lst.push_back("cherry");
            cout << "List: ";
            for (const string& s : lst) {
                cout << s << " ";
            }
            cout << endl;
        
            // deque:双端队列
            deque<double> dq;
            dq.push_back(1.1);
            dq.push_front(2.2);
            dq.push_back(3.3);
            cout << "Deque: ";
            for (double d : dq) {
                cout << d << " ";
            }
            cout << endl;
        
            return 0;
        }
        

        4.2.2 关联容器

        关联容器按键存储元素,支持高效的查找操作。

        #include <iostream>
        #include <map>
        #include <set>
        using namespace std;
        
        int main() {
            // map:键值对映射(有序)
            map<string, int> ages;
            ages["Alice"] = 25;
            ages["Bob"] = 30;
            ages["Charlie"] = 22;
            cout << "Map:" << endl;
            for (const auto& pair : ages) {
                cout << pair.first << ": " << pair.second << endl;
            }
        
            // set:唯一元素集合(有序)
            set<int> numbers;
            numbers.insert(5);
            numbers.insert(2);
            numbers.insert(8);
            numbers.insert(2); // 重复元素会被忽略
            cout << "\nSet: ";
            for (int num : numbers) {
                cout << num << " ";
            }
            cout << endl;
        
            // unordered_map:键值对映射(无序,基于哈希表)
            unordered_map<string, double> prices;
            prices["apple"] = 1.5;
            prices["banana"] = 0.8;
            prices["cherry"] = 3.2;
            cout << "\nUnordered Map:" << endl;
            for (const auto& pair : prices) {
                cout << pair.first << ": " << pair.second << endl;
            }
        
            return 0;
        }
        

        4.2.3 容器适配器

        容器适配器提供了特定的接口来操作底层容器。

        #include <iostream>
        #include <stack>
        #include <queue>
        using namespace std;
        
        int main() {
            // stack:后进先出(LIFO)
            stack<int> st;
            st.push(10);
            st.push(20);
            st.push(30);
            cout << "Stack: ";
            while (!st.empty()) {
                cout << st.top() << " ";
                st.pop();
            }
            cout << endl;
        
            // queue:先进先出(FIFO)
            queue<string> q;
            q.push("apple");
            q.push("banana");
            q.push("cherry");
            cout << "Queue: ";
            while (!q.empty()) {
                cout << q.front() << " ";
                q.pop();
            }
            cout << endl;
        
            // priority_queue:优先队列(最大堆)
            priority_queue<int> pq;
            pq.push(5);
            pq.push(2);
            pq.push(8);
            cout << "Priority Queue: ";
            while (!pq.empty()) {
                cout << pq.top() << " ";
                pq.pop();
            }
            cout << endl;
        
            return 0;
        }
        

        4.3 迭代器

        迭代器是一种对象,用于遍历容器中的元素。

        #include <iostream>
        #include <vector>
        using namespace std;
        
        int main() {
            vector<int> vec = {10, 20, 30, 40, 50};
        
            // 使用正向迭代器
            cout << "Forward iteration: ";
            for (vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) {
                cout << *it << " ";
            }
            cout << endl;
        
            // 使用常量迭代器(只读)
            cout << "Constant iteration: ";
            for (vector<int>::const_iterator cit = vec.cbegin(); cit != vec.cend(); ++cit) {
                cout << *cit << " ";
            }
            cout << endl;
        
            // 使用反向迭代器
            cout << "Reverse iteration: ";
            for (vector<int>::reverse_iterator rit = vec.rbegin(); rit != vec.rend(); ++rit) {
                cout << *rit << " ";
            }
            cout << endl;
        
            // 使用C++11的范围for循环(底层使用迭代器)
            cout << "Range-based for loop: ";
            for (int num : vec) {
                cout << num << " ";
            }
            cout << endl;
        
            return 0;
        }
        

        4.4 算法

        STL 提供了大量的通用算法,可以操作容器中的元素。

        #include <iostream>
        #include <vector>
        #include <algorithm>
        #include <numeric>
        using namespace std;
        
        int main() {
            vector<int> vec = {5, 2, 8, 1, 9, 3};
        
            // 排序
            sort(vec.begin(), vec.end());
            cout << "Sorted vector: ";
            for (int num : vec) {
                cout << num << " ";
            }
            cout << endl;
        
            // 查找元素
            auto it = find(vec.begin(), vec.end(), 8);
            if (it != vec.end()) {
                cout << "Element 8 found at position: " << distance(vec.begin(), it) << endl;
            } else {
                cout << "Element 8 not found" << endl;
            }
        
            // 计算总和
            int sum = accumulate(vec.begin(), vec.end(), 0);
            cout << "Sum of elements: " << sum << endl;
        
            // 反转容器
            reverse(vec.begin(), vec.end());
            cout << "Reversed vector: ";
            for (int num : vec) {
                cout << num << " ";
            }
            cout << endl;
        
            // 检查所有元素是否满足条件
            bool allGreater = all_of(vec.begin(), vec.end(), [](int x) { return x > 0; });
            cout << "All elements are greater than 0: " << (allGreater ? "Yes" : "No") << endl;
        
            return 0;
        }
        

        五、高级泛型技术

        5.1 模板元编程(TMP)

        模板元编程是一种在编译时执行计算的技术,利用模板实例化机制进行编译时计算。

        #include <iostream>
        using namespace std;
        
        // 编译时计算阶乘
        template <int N>
        struct Factorial {
            static const int value = N * Factorial<N-1>::value;
        };
        
        // 特化终止递归
        template <>
        struct Factorial<0> {
            static const int value = 1;
        };
        
        // 编译时判断是否为偶数
        template <int N>
        struct IsEven {
            static const bool value = (N % 2 == 0);
        };
        
        int main() {
            // 编译时计算5的阶乘
            cout << "Factorial of 5: " << Factorial<5>::value << endl;
            
            // 编译时判断7是否为偶数
            cout << "Is 7 even? " << (IsEven<7>::value ? "Yes" : "No") << endl;
            
            return 0;
        }
        

        5.2 变参模板

        变参模板允许模板接受任意数量和类型的参数。

        #include <iostream>
        using namespace std;
        
        // 递归终止函数
        void print() {
            cout << endl;
        }
        
        // 变参模板函数
        template <typename T, typename... Args>
        void print(T first, Args... args) {
            cout << first;
            if constexpr (sizeof...(args) > 0) {
                cout << ", ";
            }
            print(args...); // 递归展开参数包
        }
        
        // 计算参数的和
        template <typename T>
        T sum(T value) {
            return value;
        }
        
        template <typename T, typename... Args>
        T sum(T first, Args... args) {
            return first + sum(args...);
        }
        
        int main() {
            print(1, 2.5, "hello", 'A');
            cout << "Sum: " << sum(1, 2, 3, 4, 5) << endl;
            cout << "Sum: " << sum(1.5, 2.5, 3.5) << endl;
            
            return 0;
        }
        

        5.3 类型 traits

        类型 traits 是模板元编程的一种应用,用于在编译时获取类型信息。

        #include <iostream>
        #include <type_traits>
        using namespace std;
        
        // 模板函数,根据类型特性执行不同操作
        template <typename T>
        void process(T value) {
            if constexpr (is_integral_v<T>) {
                cout << "Processing integral type: " << value << endl;
            } else if constexpr (is_floating_point_v<T>) {
                cout << "Processing floating point type: " << value << endl;
            } else {
                cout << "Processing other type" << endl;
            }
        }
        
        int main() {
            process(42);          // 整数类型
            process(3.14);        // 浮点类型
            process("hello");     // 其他类型
            
            // 使用type_traits判断类型关系
            cout << "int is a base of double? " << is_base_of_v<int, double> << endl;
            cout << "vector<int> is a container? " << is_same_v<vector<int>::value_type, int> << endl;
            
            return 0;
        }
        

        六、泛型编程的最佳实践

        1. 保持接口简单:泛型组件的接口应尽可能简单,减少使用者的负担
        2. 提供清晰的文档:说明模板参数的要求和约束
        3. 使用概念(C++20):约束模板参数的类型要求
        4. 测试多种类型:确保泛型代码在不同类型下都能正常工作
        5. 注意性能:避免不必要的拷贝和类型转换
        6. 考虑特化:对于特定类型的特殊需求,考虑使用模板特化
        7. 利用STL:尽可能使用现有的STL组件,避免重复造轮子

        七、总结

        泛型编程是C++强大的编程范式之一,通过模板机制可以创建高效、灵活且类型安全的代码。标准模板库(STL)进一步提供了丰富的容器、算法和迭代器,大大提高了开发效率。

        掌握泛型编程技术需要理解模板的工作原理、STL的使用方法以及高级泛型技术如模板元编程和变参模板。通过合理应用泛型编程,可以编写出更加通用、复用性更强的代码。

        • 1