模板显式特化与隐式特化

10 篇文章 0 订阅

当使用一个模板时,称为实例化模板。模板实例是编译器通过将模板参数应用于模板定义而创建的具体函数或类。模板实例又称为特化。因此,rational<int>是模板rational<>的一个特化。因此,特化是针对特定一组模板参数实现模板的过程。
C++允许为一个特定的模板参数集合定义一个定制的特化;也就是说,可以创建一个规则的例外情况。当你自己定义特化而不是让编译器为你实例化模板时,它被称为显式特化(也称为完全特化)。编译器自动创建的特化将是隐式特化。

使用template<>开始一个显式特化的声明,告诉编译器正在编写一个显式特化,接下来是定义。注意类名是特化模板名称(例如Point<int>),让编译器知道正在特化什么。在可以特化一个模板之前,必须告诉编译器类模板(即原始模板)的定义。通常,会在一个单独的头文件中先写类模板声明,后跟它的特化。
显式特化完全取代了模板参数的模板声明(如果模板接受多个参数,则必须为每个参数提供一个特定的值)。尽管惯例规定Point<int>应该定义与主模板Point<>相同的所有成员,但编译器并不强制执行此类限制。也就是说特化版本的具体实现可以与原始模板不同。

#include <iostream>
#include <vector>

template<class T>
class Point{
public:
    Point(T x, T y):x_(x), y_(y){
        std::cout << __PRETTY_FUNCTION__ << std::endl;
    }

    Point(const Point& pt): x_(pt.x_), y_(pt.y_){
        std::cout << __PRETTY_FUNCTION__ << std::endl;
    }
    Point& operator=(const Point& pt)& {
        Point(pt.x_, pt.y_).swap(static_cast<Point&>(*this));
        std::cout << __PRETTY_FUNCTION__ << std::endl;

        return *this;
    }

    Point(Point&& pt) noexcept: x_(pt.x_), y_(pt.y_) {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
    }
    Point& operator=(Point&& pt)& noexcept{
        x_ = pt.x_;
        y_ = pt.y_;
        std::cout << __PRETTY_FUNCTION__ << std::endl;

        return *this;
    }

    void swap(Point& pt) noexcept{
        std::swap(x_, pt.x_);
        std::swap(y_, pt.y_);
        std::cout << __PRETTY_FUNCTION__ << std::endl;
    }

    virtual ~Point(){
        std::cout << __PRETTY_FUNCTION__ << std::endl;
    }

    T getX()const{
        return x_;
    }
    T getY()const{
        return y_;
    }

    void moveTo(T x, T y);

    /*【类内又有模板】方式一,在类内声明,在类外定义 */
    template<class U>
    U ratio() ;

    /*【类内又有模板】方式二,在类内定义 */
    template<class V>
    V multiply() {
        return static_cast<V>(x_) * static_cast<V>(y_);
    }

private:
    T x_;
    T y_;
};

template<class T>
void Point<T>::moveTo(T x, T y){
    x_ = x;
    y_ = y;
}

template<class T>
template<class U>
U Point<T>::ratio() {
    return static_cast<U>(x_) / static_cast<U>(y_); // omit devided by zero.
}


template<>
class Point<int>{
public:
    Point(int x, int y):x_(x), y_(y){
        std::cout << __PRETTY_FUNCTION__ << std::endl;
    }

    Point(const Point& pt): x_(pt.x_), y_(pt.y_){
        std::cout << __PRETTY_FUNCTION__ << std::endl;
    }
    Point& operator=(const Point& pt)& {
        Point(pt.x_, pt.y_).swap(static_cast<Point&>(*this));
        std::cout << __PRETTY_FUNCTION__ << std::endl;

        return *this;
    }

    Point(Point&& pt) noexcept: x_(pt.x_), y_(pt.y_) {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
    }
    Point& operator=(Point&& pt)& noexcept{
        x_ = pt.x_;
        y_ = pt.y_;
        std::cout << __PRETTY_FUNCTION__ << std::endl;

        return *this;
    }

    void swap(Point& pt) noexcept{
        std::swap(x_, pt.x_);
        std::swap(y_, pt.y_);
        std::cout << __PRETTY_FUNCTION__ << std::endl;
    }

    virtual ~Point(){
        std::cout << __PRETTY_FUNCTION__ << std::endl;
    }

    int getX()const{
        return x_;
    }
    int getY()const{
        return y_;
    }

    void moveTo(int x, int y){
        x_ = x;
        y_ = y;
    }

    double ratio(){
        std::cout << "Specialized version of type int.\n";
        return static_cast<double>(x_) / static_cast<double>(y_); // omit devided by zero.
    }

    double multiply() {
        return static_cast<double>(x_) * static_cast<double>(y_);
    }

private:
    int x_;
    int y_;
};

int main() {
    Point<int> pt1(1, 2);
    Point<float> pt2(2.3f, 4.5f);
    Point<double> pt3(2.3, 4.5);

    pt1.ratio();
    pt2.ratio<double>();
}

输出:

Point<int>::Point(int, int)
Point<T>::Point(T, T) [with T = float]
Point<T>::Point(T, T) [with T = double]
Specialized version of type int.
Point<T>::~Point() [with T = double]
Point<T>::~Point() [with T = float]
virtual Point<int>::~Point()

由输出可以看出int版用的是特化版本,而且 double ratio()的实现与原始模板也不同(输出了Specialized version of type int.)。

Reference

Exploring C++ 11, 2nd Edition.

  • 9
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值