天天看點

【C++深度解析】44、類模闆深度剖析--模闆特化

文章目錄

    • 1 多參數類模闆
    • 2 類模闆特化
    • 3 函數模闆特化
    • 4 小結

  • 類模闆可以定義任意多不同的類型參數
【C++深度解析】44、類模闆深度剖析--模闆特化

類模闆可以被特化

  • 指定類模闆的特定實作
  • 部分類型參數必須顯示指定
  • 根據類型參數分開實作類模闆
  • 編譯器自動擇優選擇
【C++深度解析】44、類模闆深度剖析--模闆特化

類模闆特化可以分為部分特化和完全特化兩種類型

  • 部分特化–>用特定規則限制類型參數
  • 完全特化–>完全顯示指定類型參數
【C++深度解析】44、類模闆深度剖析--模闆特化

程式設計實驗:類模闆特化

// 44-1.cpp
#include<iostream>
using namespace std;
template<typename T1, typename T2>
class Test
{
public:
    void add(T1 a, T2 b)
    {
        cout << "void add(T1 a, T2 b)" << endl;
        cout << a + b << endl;
    }
};

template<typename T1, typename T2>
class Test<T1*, T2*>				// 關于指針的特化實作
{
public:
    void add(T1* a, T2* b)
    {
        cout << "void add(T1* a, T2* b)" << endl;
        cout << *a + *b << endl;
    }
};

template<typename T>
class Test<T, T>					// 當 Test 類模闆的兩個類型參數完全相同時,使用這個實作
{
public:
    void add(T a, T b)
    {
        cout << "void add(T a, T b)" << endl;
        cout << a + b << endl;
    }
    void print()
    {
        cout << "class Test<T, T>" << endl;
    }
};

template<>
class Test<void*, void*>			// 當 T1 == void* 并且 T2 == void* 時
{
public:
    void add(void* a, void* b)
    {
        cout << "void add(void* a, void* b)" << endl;
        cout << "Error to add void* param..." << endl;
    }
};
int main()
{
    Test<int, float>t1;			// 必須顯示指明每一個類型參數
    Test<long, long>t2;
    Test<void*, void*>t3;

    t1.add(1, 2.5);
    t2.add(5, 5);
    t2.print();

    t3.add(NULL, NULL);

    Test<int*, double*>t4;
    int a = 1;
    double b = 0.1;
    t4.add(&a, &b);
    return 0;
}
           
  • 上面的代碼先定義了一個模闆類,然後給出了三個特化實作。特化本質上是同一個類模闆。編譯器總是選擇最比對的進行實作。
  • t1.add(1, 2.5); 調用 class Test
  • t2.add(5, 5); 調用 class Test<T, T>
  • t3.add(NULL, NULL); 調用 class Test<void*, void*>
  • t4.add(&a, &b); 調用 class Test<T1*, T2*>
$ g++ 44-1.cpp -o 44-1
$ ./44-1
void add(T1 a, T2 b)
3.5
void add(T a, T b)
10
class Test<T, T>
void add(void* a, void* b)
Error to add void* param...
void add(T1* a, T2* b)
1.1
           

注意事項:

  • 特化本質上屬于同一類模闆,隻是模闆的分開實作
  • 特化類模闆的使用方式是統一的,必須顯示指定每一個類型參數

函數模闆隻支援類型參數完全特化

【C++深度解析】44、類模闆深度剖析--模闆特化

程式設計實驗:函數模闆特化

// 44-2.cpp
#include<iostream>
using namespace std;
template<typename T>
bool Equal(T a, T b)
{
    cout << "bool Equal(T a, T b)" << endl;
    return a == b;
}

template<>
bool Equal<double>(double a, double b)
{
    const double delta = 0.00000000000001;
    double r = a - b;
    cout << "bool Equal<double>(double a, double b)" << endl;
    return (-delta < r) && (r < delta);
}

bool Equal(double a, double b)
{
    const double delta = 0.00000000000001;
    double r = a - b;
    cout << "bool Equal(double a, double b)" << endl;
    return (-delta < r) && (r < delta);
}
int main()
{
    cout << Equal(1, 1) << endl;
    cout << Equal<>(0.01, 0.01) << endl;		// 指定使用模闆
    cout << Equal(0.1, 0.1) << endl;
    return 0;
}
           
  • bool Equal(T a, T b) 是函數模闆,兩個浮點數比較不能直接使用 ‘==’,是以實作函數模闆特化 bool Equal(double a, double b),函數模闆隻能完全特化。二者本質上屬于同一模闆,隻是分開實作
  • bool Equal(double a, double b) 是函數重載。
  • Equal(1, 1) 将選擇模闆 bool Equal(T a, T b)
  • Equal<>(0.01, 0.01) 使用模闆 bool Equal<double>(double a, double b)
  • Equal(0.1, 0.1) 使用重載函數 bool Equal(double a, double b),
$ g++ 44-2.cpp -o 44-2
$ ./44-2
bool Equal(T a, T b)
1
bool Equal<double>(double a, double b)
1
bool Equal(double a, double b)
1
           

繼續閱讀