玩命加载中 . . .

16.5-模板特例化


函数模板特例化

之前的compare不能处理字符指针,我们可以特例化一个处理字符指针的版本

template<typename T>
int compare(const T&, const T&);

template<>
int compare(const char* const& p1, const char* const& p2) {
    return strcmp(p1, p2);
}

将T特例化为const char*,原模板中的参数是指向T类型的const引用,一个指针类型的const版本是一个常量指针而不是指向const类型的指针,所以我们需要将T特例化为指向const的字符指针

特例化的本质是实例化一个模板,而非重载它,因此特例化不影响函数匹配

如果一个程序使用一个特例化版本,而同时原模板的一个实例具有相同的模板实参集合,我们本意是调用特例化版本,但因为特例化版本不在作用域中,所以就调用到了原模板的实例化版本,出现与预期不符的结果

模板及其特例化版本应该声明在同一个头文件中,所有同名模板的声明应该放在前面,然后是这些模板的特例化版本

类模板特例化

可以特例化一个hash模板类的特例化版本,用来存储Sales_data对象

namespace std
{   // 打开std命名空间,以便特例化std::hash
    template<>
    struct hash<Sales_data> {
        typedef size_t result_type;
        typedef	Sales_data argument_type;
        size_t operator()(const Sales_data& s) const;
    };
    size_t hash<Sales_data>::operator()(const Sales_data &s) const {
    return hash<string>()(s.bookNo) ^
            hash<unsigned>()(s.units_sold) ^
            hash<double>()(s.revenue);
    }
}   // 关闭std命名空间,注意没有分号

需要声明为Sales_data的友元

template<class T> class std::hash;
class Sales_data {
    friend class std::hash<Sales_data>;
};

类模板部分特例化

类模板也可以特例化。与函数模板不同,类模板的特例化不必为所有模板参数提供实参,可以只指定一部分模板参数。一个类模板的部分特例化(partial specialization)版本本身还是一个模板,用户使用时必须为那些未指定的模板参数提供实参

只能部分特例化类模板,不能部分特例化函数模板。

由于类模板的部分特例化版本是一个模板,所以需要定义模板参数。对于每个未完全确定类型的模板参数,在特例化版本的模板参数列表中都有一项与之对应。在类名之后,需要为特例化的模板参数指定实参,这些实参位于模板名之后的尖括号中,与原始模板中的参数按位置相对应

// 通用版本
template <typename T>
struct remove_reference {
    typedef T type;
};

// 部分特例化版本
template <typename T>
struct remove_reference<T &> {  // 左值引用
    typedef T type;
};

template <typename T>
struct remove_reference<T &&> { // 右值引用
    typedef T type;
};

int i;
// decltype(42)为int,使用原始模板
remove_reference<decltype(42)>::type a;

// decltype(i)为int&,使用左值引用的部分特例化版本
remove_reference<decltype(i)>::type b;

// decltype(std::move(i))为int&&,使用右值引用的部分特例化版本
remove_reference<decltype(std::move(i))>::type c;

abc均为int类型

特例化类的成员

可以只特例化类模板的指定成员函数,而不用特例化整个模板

template <typename T>
struct Foo {
    Foo(const T& t = T()): mem(t) { }
    void Bar() { /* ... */ }
    T mem;
};

template<>
void Foo<int>::Bar() {  // 特例化Foo<int>的成员Bar
    // ...
}

Foo<string> fs; // 实例化Foo<string>::Foo()
fs.Bar();       // 实例化Foo<string>::Bar()
Foo<int> fi;    // 实例化Foo<int>::Foo()
fi.Bar();       // 使用特例化版本的Foo<int>::Bar()

文章作者: kunpeng
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 kunpeng !
  目录