C++类模板的特化(三)

本文主要介绍类模板的特化、局部特化和缺省模板实参;

1.类模板的特化

类模板的特化(Class Template Specialization)是指为特定的模板参数提供自定义实现的过程。通过特化,我们可以针对某些特定的类型或条件提供不同的行为或实现;

如果需要特化一个类模板,需要特化该模板中的所有成员函数;

模板的特化注意事项:
需要将模板写成template <>,并且需要指明特定的类型,下面示例需要特化std::string的类型,成员函数按照正常的函数实现即可

template <>
class Stack <std::string>
{}

示例

/*
 * @brief: class complates
 * @complie: g++ -g *.cc -o d -std=c++11
 * @autor: your name
 * @date: 2023/08/22
 */

#include <iostream>
#include <vector>
#include <stdexcept>

template <class T>
class Stack 
{
private:
    std::vector<T> elems;

public:
    void push(T const&);
    void pop();
    T top() const;
    bool empty() const
    {
        return elems.empty();
    }    
    int32_t getElemsSize() const
    {
        std::cout<<"not string size"<<std::endl;
        return elems.size();
    }
};

template <typename T>
void Stack<T>::push(T const& elem)
{
    elems.push_back(elem);
}

template <typename T>
void Stack<T>::pop()
{
    if(elems.empty()) 
    {
        throw std::out_of_range("empty stack");
    }
    elems.pop_back();
}

template <typename T>
T Stack<T>::top() const
{
    if(elems.empty()) 
    {
        throw std::out_of_range("empty stack");
    }
    return elems.back();
}


//std::string
template <>
class Stack <std::string>
{
private:
    std::vector<std::string> elems;

public:
    void push(std::string const&);
    void pop();
    std::string top() const;
    bool empty() const
    {
        return elems.empty();
    }    
    int32_t getElemsSize() const
    {
        std::cout<<"string size"<<std::endl;
        return elems.size();
    }
};

void Stack<std::string>::push(std::string const& elem)
{
    elems.push_back(elem);
}

void Stack<std::string>::pop()
{
    if(elems.empty()) 
    {
        throw std::out_of_range("empty stack");
    }
    elems.pop_back();
}

std::string Stack<std::string>::top() const
{
    if(elems.empty()) 
    {
        throw std::out_of_range("empty stack");
    }
    return elems.back();
}

int main(int argc, char* argv[])
{
    Stack<int> int_stack;
    int_stack.push(10);
    int_stack.push(20);
    int_stack.push(30);
    std::cout<<int_stack.getElemsSize()<<std::endl;

    //std::string
    Stack<std::string> string_stack;
    string_stack.push("class");
    string_stack.push("int");
    string_stack.push("int64");
    string_stack.push("double");
    string_stack.push("float");
    std::cout<<string_stack.getElemsSize()<<std::endl;


    return 0;
}

2. 类模板的局部特化

类模板的局部特化(Partial Class Template Specialization)是指针对模板参数的部分特化,只针对某些特定的条件进行自定义实现的过程。通过局部特化,我们可以为满足特定条件的模板参数提供不同的实现。

示例

/*
 * @brief: class complates
 * @complie: g++ -g *.cc -o d -std=c++11
 * @autor: your name
 * @date: 2023/08/22
 */

#include <iostream>
#include <vector>
#include <stdexcept>
#include <string>

//局部特化
template <typename T, typename U>
class MyClass
{
public:
    void print() const
    {
        std::cout<<"typename and typename"<<std::endl;
    }
};

template <typename T>
class MyClass<T, std::string>
{
public:
    void print() const
    {
        std::cout<<"typename and string"<<std::endl;
    }
};

template <typename T>
class MyClass<T, double>
{
public:
    void print() const
    {
        std::cout<<"typename and double"<<std::endl;
    }
};



int main(int argc, char* argv[])
{
    MyClass<int, int> int_myclass;
    int_myclass.print();

    MyClass<int, std::string> string_myclass;
    string_myclass.print();

    MyClass<int, double> double_myclass;
    double_myclass.print();

    return 0;
}

输出

typename and typename
typename and string
typename and double

3. 缺省模版实参

在函数模板的时候,可以将模板的参数定位为缺省值;即支持默认,也支持指定,使用起来更加的方便;

示例

/*
 * @brief: class complates
 * @complie: g++ -g *.cc -o d -std=c++11
 * @autor: your name
 * @date: 2023/08/22
 */

#include <iostream>
#include <vector>
#include <deque>
#include <stdexcept>
#include <string>

//缺省模版参数
template <typename T, typename CONT = std::vector<T>>
class Stack 
{
private:
    CONT elems;

public:
    void push(T const&);
    void pop();
    T top() const;
    bool empty() const
    {
        return elems.empty();
    }    
    int32_t getElemsSize() const
    {        
        return elems.size();
    }
};

template <typename T, typename CONT>
void Stack<T, CONT>::push(T const& elem)
{
    elems.push_back(elem);
}

template <typename T, typename CONT>
void Stack<T, CONT>::pop()
{
    if(elems.empty()) 
    {
        throw std::out_of_range("empty stack");
    }
    elems.pop_back();
}

template <typename T, typename CONT>
T Stack<T, CONT>::top() const
{
    if(elems.empty()) 
    {
        throw std::out_of_range("empty stack");
    }
    return elems.back();
}


int main(int argc, char* argv[])
{
    //使用默认值
    Stack<int> int_stack;
    int_stack.push(10);
    int_stack.push(20);
    int_stack.push(30);
    std::cout<<int_stack.top()<<std::endl;

    //赋值类型
    Stack<double, std::deque<double>> double_stack;
    double_stack.push(10.11);
    double_stack.push(20.22);
    double_stack.push(30.33);
    std::cout<<double_stack.top()<<std::endl;

    return 0;
}

输出

30
30.33