S SmartDocs
Série: C++ cpp 236 lignes · Mis à jour 2026-04-03

template_specialization.cpp

C++/Part3_泛型與STL/Ch12_模板程式設計/template_specialization.cpp

// template_specialization.cpp
// 模板特化示範:完整特化與部分特化
// 編譯:g++ -std=c++17 -Wall -o template_specialization template_specialization.cpp

#include <iostream>
#include <string>
#include <cstring>
#include <type_traits>

// ============================================================
// 1. 函式模板的完整特化
// ============================================================

// 通用版本
template <typename T>
bool is_equal(const T& a, const T& b) {
    return a == b;
}

// 針對 const char* 的完整特化——用 strcmp 比較內容而非指標位址
template <>
bool is_equal<const char*>(const char* const& a, const char* const& b) {
    return std::strcmp(a, b) == 0;
}

// 針對 double 的完整特化——允許浮點誤差
template <>
bool is_equal<double>(const double& a, const double& b) {
    return std::abs(a - b) < 1e-9;
}

// ============================================================
// 2. 類別模板的完整特化 — Printer<T>
// ============================================================

// 通用版本
template <typename T>
class Printer {
public:
    void print(const T& value) const {
        std::cout << "[通用] 值: " << value << std::endl;
    }
};

// 針對 std::string 的完整特化
template <>
class Printer<std::string> {
public:
    void print(const std::string& value) const {
        std::cout << "[std::string] \"" << value
                  << "\" (長度: " << value.size() << ")" << std::endl;
    }
};

// 針對 const char* 的完整特化
template <>
class Printer<const char*> {
public:
    void print(const char* const& value) const {
        std::cout << "[const char*] \"" << value
                  << "\" (長度: " << std::strlen(value) << ")" << std::endl;
    }
};

// 針對 bool 的完整特化
template <>
class Printer<bool> {
public:
    void print(const bool& value) const {
        std::cout << "[bool] " << (value ? "true(真)" : "false(假)")
                  << std::endl;
    }
};

// ============================================================
// 3. 類別模板的部分特化
// ============================================================

// 通用版本:Container<T>
template <typename T>
class TypeInfo {
public:
    void describe() const {
        std::cout << "TypeInfo<T>: 一般型別" << std::endl;
    }
};

// 部分特化:指標型別 T*
template <typename T>
class TypeInfo<T*> {
public:
    void describe() const {
        std::cout << "TypeInfo<T*>: 指標型別(指向某個型別的指標)" << std::endl;
    }
};

// 部分特化:參考型別 T&
template <typename T>
class TypeInfo<T&> {
public:
    void describe() const {
        std::cout << "TypeInfo<T&>: 左值參考型別" << std::endl;
    }
};

// 部分特化:const T
template <typename T>
class TypeInfo<const T> {
public:
    void describe() const {
        std::cout << "TypeInfo<const T>: 常數型別" << std::endl;
    }
};

// ============================================================
// 4. 多參數類別模板的部分特化
// ============================================================

// 通用版本
template <typename T, typename U>
class PairPrinter {
public:
    void print(const T& first, const U& second) const {
        std::cout << "[不同型別] (" << first << ", " << second << ")" << std::endl;
    }
};

// 部分特化:兩個型別參數相同
template <typename T>
class PairPrinter<T, T> {
public:
    void print(const T& first, const T& second) const {
        std::cout << "[相同型別] (" << first << ", " << second << ")" << std::endl;
    }
};

// 部分特化:第二個參數是指標
template <typename T, typename U>
class PairPrinter<T, U*> {
public:
    void print(const T& first, const U* second) const {
        std::cout << "[含指標] (" << first << ", *" << *second << ")" << std::endl;
    }
};

// ============================================================
// 主程式
// ============================================================
int main() {
    std::cout << "========================================" << std::endl;
    std::cout << "  模板特化(Template Specialization)示範" << std::endl;
    std::cout << "========================================\n" << std::endl;

    // --- 1. 函式模板的完整特化 ---
    std::cout << "--- 1. 函式模板完整特化 is_equal ---" << std::endl;

    std::cout << "is_equal(10, 10)      = "
              << std::boolalpha << is_equal(10, 10) << std::endl;
    std::cout << "is_equal(10, 20)      = "
              << is_equal(10, 20) << std::endl;

    // 使用 const char* 特化版本(比較字串內容)
    const char* s1 = "hello";
    const char* s2 = "hello";
    const char* s3 = "world";
    std::cout << "is_equal(\"hello\", \"hello\") = "
              << is_equal(s1, s2) << std::endl;
    std::cout << "is_equal(\"hello\", \"world\") = "
              << is_equal(s1, s3) << std::endl;

    // 使用 double 特化版本(容許浮點誤差)
    std::cout << "is_equal(0.1+0.2, 0.3)    = "
              << is_equal(0.1 + 0.2, 0.3) << std::endl;

    std::cout << std::endl;

    // --- 2. 類別模板完整特化 Printer ---
    std::cout << "--- 2. 類別模板完整特化 Printer<T> ---" << std::endl;

    Printer<int> int_printer;
    int_printer.print(42);

    Printer<double> dbl_printer;
    dbl_printer.print(3.14159);

    Printer<std::string> str_printer;
    str_printer.print("Hello, 模板特化!");

    Printer<const char*> cstr_printer;
    cstr_printer.print("C-style string");

    Printer<bool> bool_printer;
    bool_printer.print(true);
    bool_printer.print(false);

    std::cout << std::endl;

    // --- 3. 部分特化 TypeInfo ---
    std::cout << "--- 3. 類別模板部分特化 TypeInfo ---" << std::endl;

    TypeInfo<int> t1;
    t1.describe();          // 一般型別

    TypeInfo<int*> t2;
    t2.describe();          // 指標型別

    TypeInfo<int&> t3;
    t3.describe();          // 左值參考型別

    TypeInfo<const int> t4;
    t4.describe();          // 常數型別

    TypeInfo<double*> t5;
    t5.describe();          // 指標型別

    std::cout << std::endl;

    // --- 4. 多參數部分特化 PairPrinter ---
    std::cout << "--- 4. 多參數部分特化 PairPrinter ---" << std::endl;

    PairPrinter<int, double> pp1;
    pp1.print(42, 3.14);   // 不同型別

    PairPrinter<int, int> pp2;
    pp2.print(10, 20);     // 相同型別

    int value = 100;
    PairPrinter<std::string, int*> pp3;
    pp3.print("指標值", &value);  // 含指標

    std::cout << "\n========================================" << std::endl;
    std::cout << "  模板特化示範結束" << std::endl;
    std::cout << "========================================" << std::endl;

    return 0;
}

Articles liés