偏特化(Partial Specialization)理解

偏特化(Partial Specialization)理解

偏特化 是指:当模板有多个参数时,只对部分参数进行特化,而不是全部特化。

核心概念对比

特化类型 参数情况 示例
全特化 所有参数都固定 template<> class X<int, double>
偏特化 只固定部分参数 template<class T> class X<T, int>

1. 基础示例理解

cpp 复制代码
// 主模板:通用的情况
template<typename T1, typename T2>
class MyClass {
public:
    void print() { cout << "General version" << endl; }
};

// 偏特化1:第二个参数固定为 int
template<typename T1>
class MyClass<T1, int> {
public:
    void print() { cout << "Partial: second is int" << endl; }
};

// 偏特化2:两个参数都是指针
template<typename T1, typename T2>
class MyClass<T1*, T2*> {
public:
    void print() { cout << "Partial: both pointers" << endl; }
};

// 偏特化3:两个参数相同类型
template<typename T>
class MyClass<T, T> {
public:
    void print() { cout << "Partial: same type" << endl; }
};

// 使用示例
MyClass<double, string> obj1;  // 使用主模板
MyClass<double, int> obj2;     // 使用偏特化1
MyClass<int*, double*> obj3;   // 使用偏特化2
MyClass<int, int> obj4;        // 使用偏特化3

2. 为什么需要偏特化?

cpp 复制代码
// 场景:一个存储容器,但对指针类型特殊处理
template<typename T>
class Storage {
    T data;
public:
    void set(const T& val) { data = val; }
    T get() { return data; }
};

// 偏特化:T 为指针类型时,使用不同的实现
template<typename T>
class Storage<T*> {  // 注意:这里 T 仍然可以变化
    T* data;
public:
    void set(T* val) { 
        data = new T(*val);  // 指针需要深拷贝
    }
    T* get() { 
        return data; 
    }
    ~Storage() { delete data; }
};

// 使用
Storage<int> s1;      // 普通类型
s1.set(100);          // 直接拷贝

Storage<int> s2;      // 指针类型,使用偏特化版本
int* p = new int(200);
s2.set(p);            // 会深拷贝

3. 常见偏特化模式

cpp 复制代码
// 模式1:固定一个类型
template<typename T, typename Alloc>
class MyVector {};

template<typename T>
class MyVector<T, std::allocator<T>> {};

// 模式2:指针偏特化
template<typename T>
class Wrapper {};

template<typename T>
class Wrapper<T*> {};

// 模式3:const 偏特化
template<typename T>
class Processor {};

template<typename T>
class Processor<const T> {};

// 模式4:引用偏特化
template<typename T>
class Handler {};

template<typename T>
class Handler<T&> {};

// 模式5:数组偏特化
template<typename T, int N>
class ArrayWrapper {};

template<typename T>
class ArrayWrapper<T, 0> {};  // 空数组特化

4. 实际应用:智能指针的偏特化

cpp 复制代码
// 简化的智能指针实现
template<typename T>
class SmartPtr {
    T* ptr;
public:
    SmartPtr(T* p) : ptr(p) {}
    T* operator->() { return ptr; }
    T& operator*() { return *ptr; }
};

// 偏特化:针对数组类型
template<typename T>
class SmartPtr<T[]> {  // 数组版本
    T* ptr;
public:
    SmartPtr(T* p) : ptr(p) {}
    T& operator[](int index) { return ptr[index]; }
    ~SmartPtr() { delete[] ptr; }
};

// 使用
SmartPtr<int> p1(new int(5));     // 普通指针
*p1 = 10;                         // OK

SmartPtr<int[]> p2(new int[10]);  // 数组指针
p2[0] = 5;                        // 支持下标访问

5. 偏特化的限制

cpp 复制代码
// ❌ 错误:不能偏特化函数模板
template<typename T>
void func(T x) {}

template<typename T>  // 错误!函数不能偏特化
void func<T*>(T* x) {}

// ✅ 正确:用重载代替
template<typename T>
void func(T x) {}

template<typename T>
void func(T* x) {}  // 函数重载

// ❌ 错误:不能偏特化类模板的成员函数
template<typename T>
class Demo {
    void method();
};

// 错误!不能只偏特化成员函数
template<typename T>
void Demo<T*>::method() {}

6. 偏特化 vs 重载

cpp 复制代码
// 类模板:只能用偏特化
template<typename T>
class Container {};

template<typename T>
class Container<T*> {};  // 偏特化

// 函数模板:用重载,不用偏特化
template<typename T>
void process(T val) {}

template<typename T>
void process(T* val) {}  // 重载,不是偏特化

7. 匹配优先级

编译器选择最特化的版本:

cpp 复制代码
template<typename T> class X {};           // 主模板(通用)
template<typename T> class X<T*> {};       // 偏特化1
template<typename T> class X<const T*> {}; // 偏特化2

X<int> x1;           // 主模板
X<int*> x2;          // 偏特化1(匹配指针)
X<const int*> x3;    // 偏特化2(匹配 const 指针)

理解要点总结

  1. 偏特化 = 部分特殊化,不是全部固定
  2. 语法template<剩余参数> class 类名<固定参数, 剩余参数>
  3. 目的:对特定模式进行特殊处理(如指针、const、数组等)
  4. 只能用于类模板,函数模板用重载代替
  5. 更特化的版本优先匹配
  6. 偏特化参数必须是主模板参数的子集

记忆口诀:全特化锁定所有类型,偏特化锁定类型模式,指针、数组、const 都可以偏特化处理。

相关推荐
博客180015 小时前
酷宝的使用方法,超好用的免费界面库,C++、MFC可用
c++·mfc·界面库·库来帮·酷宝
郝学胜_神的一滴16 小时前
CMake 026:属性体系精讲、四大作用域全解 & 实战代码落地
c++·cmake
众少成多积小致巨1 天前
JNI (Java Native Interface) 技术手册中文参考指南
android·java·c++
clint4565 天前
C++进阶(1)——前景提要
c++
夜悊6 天前
C++代码示例:进制数简单生成工具
c++
郝学胜_神的一滴6 天前
CMake 021: IF 条件判据详诠
c++·cmake
_wyt0016 天前
洛谷 B3930 [GESP202312 五级] 烹饪问题 题解
c++·gesp
玖玥拾6 天前
C/C++ 数据结构(七)栈、容器适配器
c语言·数据结构·c++··容器适配器
один but you6 天前
constexpr函数
c++
凡人叶枫6 天前
Effective C++ 条款41:了解隐式接口和编译期多态
java·开发语言·c++·effective c++