C++ class templates(2)---《C++ Templates》

7 篇文章 0 订阅
1 篇文章 0 订阅

摘要:
1)讲具体类型当做template arguements传入才能使用class template。于是该class template便以你所指定的那些类型,由编译器实例化并编译;
2)class template之中,只有被实际调用的成员函数,才能被实例化;
3)针对某些特定类型,可以针对class template进行全特化和偏特化;
4)可以为template parameters定义默认值,即预设模板变量值。
**

实作class template stack

**

#include <vector>
#include <stdexcept>

template <typename T>
class Stacck{
private:
    std::vector<T> elems;
public:
    void push(T const&);
    void pop();
    T top() const;
    bool empty() const{
        return elems.empty();
    }
};
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("Stack<>::pop: empty stack");
        }
    T elem=elems.back();
    elems.pop_back();
    return elem;
}
template <typename T>
T Stack<T>::top() const{
    if(elems.empty()){
        throw std::out_of_range("Stak<>::top empty stack");
    }
    return elems.back();
}

这个class template是以标准库的class template vector<>为基础构建起来的。这里的typename也可以用class进行代替,这两个几乎没有差异,我么也可以为自己声明Stack类声明copy构造函数和assignment运算符,可以这样写:

template <typename T>
class Stack{
    ...
    Stack(Stack<T> const&);
    Stack<T>& operator=(Stack<T> const&);
    ...
};

然而如果只是需要class名称而不是class类型时,只需写Stack即可,构造函数和析构函数的声明属于这种情况。

**

使用class template

**

#include <iostream>
#include <string>
#include <cstdlib>
#include "stack.hpp"

int main(){
    try{
        Stack<int> intStack;
        Stack<string> stringStack;
        intStack.push(7);
        std::cout<<intStack.pop()<<std::endl;
        stringStack.push("hello");
        std::cout<<stringStack.top()<<std::endl;
        stringStack.pop();
        stringStack.pop();
    }catch(std::exception const& ex){
        std::cerr<<"Exception:"<<ex.what()<<std::endl;
        return EXIT_FAILURE;
    }
}

需要注意的是,惟有被调用到的成员函数,才会被实例化。对于class template而言,只有当某个成员函数被调用时候,才回进行实例化。无疑这样做可以节省时间和空间。另一个好处是,你甚至可以实例化一个class template,而具体实现类型并不需要完整支持内部的部分不会被调用到的函数,举例如下:考虑么讴歌class,其某些成员函数使用operator<对内部元素进行排序;只要避免调用这些函数,就可以以一个不支持operator<的类型来实例化这个class template。
运用typedef,你可以更方便地使用class templates:

typedef Stack<int> IntStack;
void foo(IntStack const& s){
    IntStack isStack[10];
    ...
}
Stack<float*> floatPtrStack;
Stack<Stack<int> > intStackStack;//Stack of Stack

注意,你必须在相邻的两个右角括号之间插入一些空白符号,否则就等于使用了operator>>,就会导致语法错误。

**

class Template的特化

**
针对某些特殊的template arguments,对一个class template进行特化,class template特化与fucntion template的重载类似,使你得以针对某些特定类型进行程序代码优化,或者修正某个特定类型在class template实例中的错误行为。如果你对一个class template进行特化,就必须特化所有成员函数。
特化必须以template<>开头声明此一class,后面耕者你希望的特化结果,特化类型将作为template arguments并在class名称之后直接写明:

template <>
class Stack<std::string>{
    ...
};
//特化函数而言,每个T出现处都应该更换为特化类型
void Stack<std::string>::push(std::string const& elem){
    elems.push_back(elem);
}

下面给出一个针对std::string类型特化Stack<>的完整示例:

#include <deque>
#include <string>
#include <stdexcept>
#include "stack.hpp"
template<>
class Stack<std::string>{
private:
    std::deque<std::string> elems;
public:
    void push(std::string const&);
    void pop();
    std::string top() const;
    bool empty() const{
        return elems.empty();
    }
};
void Stack<std::string>::push(std::string const& elem){
    elem.push_back(elem);
}
void Stack<std::string>::pop(){
    if(elems.empty()){
        throw std::out_of_range("Stack<std::string>::pop():empty stack");
    }
    elems.pop_back();
}
std::string Stack<std::string>::top() const{
    if(elems.empty()){
        throw std::out_of_range("Stack<std::string>::top(): empty stack");
    }
    return elems.back();
}

该例中,我们在stack类中改用deque来管理替代元素,这样做并没有特别的好处,但它示范了一个特化实作码可以和其primary template有一定程度的差异,哈哈,这是不是类似于function template中函数重载呀!

**

偏特化(Partial Specialization)

**
class template不仅可以被全特化,更重要的是其可以被偏特化,强大吧!这时的我们可以在特定情况下使用特殊实作码,但仍然留给使用者选择template parameter的能力!例如针对如下class template:

template <typename T1,typename T2>
class MyClass{
    ...
}

以下书中形式的偏特化都是合理的:

template <typename T>
class MyClass<T,T>{
    ...
};
template <typename T>
class MyClass<T,int>{
    ...
};
template <typename T1,typename T2>
class MyClass<T1*,T2*>{
    ...
};
MyClass<int,float> mif;//使用Myclass<T1,T2>
Myclass<float,float> mff;//使用Myclass<T,T>
MyClass<float,int> mfi;//使用MyClass<T,int>
MyClass<int*,float*> mp;//使用<T1*,T2*>
MyClass<int,int> m;//使用???,匹配了两种
MyClass<int*,int*> m;//使用???,匹配了两种

为了解决上面的歧义性,可以针对相同类型的指针,再提供一种偏特化版本:

template <typename T>
class MyClass<T*,T*>{
    ...
};

**

预设模板自变量

**
我们可以针对class template定义其template parameters的默认值,称为default template arguments(预设模板自变量)

#include <vector>
#include <stdexcept>

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();
    }
}
//因为template现在有两个参数,因此每一个成员函数的定义式中都必须包含这两个参数
template <typename T,typename CONT>
void Stack<T,CONT>::pop(){
    if(elems.empty()){
        throw std::out_of_range("Stack<>::pop(): empty stack");
    }
    elems.pop_back();
}
template <typename T,typename CONT>
T stack<T,CONT>::top() const{
    if(elems.empty()){
        throw std::out_of_range("Stack<>::top(): empty stack");
    }
    return elems.back();
}
template <typename T,typename CONT>
void Stack<T,CONT>::push(T const& elem){
    elems.push_back(elem);
}

调用

#include <iostream>
#include <deque>
#include <cstdlib>
#include "stack.hpp"
int main(){
    try{
        Stack<int> intStack;
        Stack<double,std::deque<double> >dblStack;
        intStack.push(7);
        std::cout<<intStack.top()<<std::endl;
        intStack.pop();
        dblStack.push(42.42);
        std::cout<<dblStack.top()<<std::endl;
        dblStack.pop();
        dblStack.pop();
    }catch(std::exception const& ex){
        std::cerr<<"Exception:"<<ex.what()<<std::endl;
        return EXIT_FAILURE;
    }
}

注意上述代码中的intStack和dblStack的声明方式。

Templates are among the most powerful features of C++, but they remain misunderstood and underutilized, even as the C++ language and development community have advanced. In C++ Templates, Second Edition, three pioneering C++ experts show why, when, and how to use modern templates to build software that’s cleaner, faster, more efficient, and easier to maintain. Now extensively updated for the C++11, C++14, and C++17 standards, this new edition presents state-of-the-art techniques for a wider spectrum of applications. The authors provide authoritative explanations of all new language features that either improve templates or interact with them, including variadic templates, generic lambdas, class template argument deduction, compile-time if, forwarding references, and user-defined literals. They also deeply delve into fundamental language concepts (like value categories) and fully cover all standard type traits. The book starts with an insightful tutorial on basic concepts and relevant language features. The remainder of the book serves as a comprehensive reference, focusing first on language details and then on coding techniques, advanced applications, and sophisticated idioms. Throughout, examples clearly illustrate abstract concepts and demonstrate best practices for exploiting all that C++ templates can do. Understand exactly how templates behave, and avoid common pitfalls Use templates to write more efficient, flexible, and maintainable software Master today’s most effective idioms and techniques Reuse source code without compromising performance or safety Benefit from utilities for generic programming in the C++ Standard Library Preview the upcoming concepts feature The companion website, tmplbook.com, contains sample code and additional updates.
C++ Template第二版,2017年9月16日出版 Templates are among the most powerful features of C++, but they remain misunderstood and underutilized, even as the C++ language and development community have advanced. In C++ Templates, Second Editi on, three pioneering C++ experts show why, when, and how to use modern templates to build software that’s cleaner, faster, more efficient, and easier to maintain. Now extensively updated for the C++11, C++14, and C++17 standards, this new edition presents state-of-the-art techniques for a wider spectrum of applications. The authors provide authoritative explanations of all new language features that either improve templates or interact with them, including variadic templates, generic lambdas, class template argument deduction, compile-time if, forwarding references, and user-defined literals. They also deeply delve into fundamental language concepts (like value categories) and fully cover all standard type traits. The book starts with an insightful tutorial on basic concepts and relevant language features. The remainder of the book serves as a comprehensive reference, focusing first on language details and then on coding techniques, advanced applications, and sophisticated idioms. Throughout, examples clearly illustrate abstract concepts and demonstrate best practices for exploiting all that C++ templates can do. Understand exactly how templates behave, and avoid common pitfalls Use templates to write more efficient, flexible, and maintainable software Master today’s most effective idioms and techniques Reuse source code without compromising performance or safety Benefit from utilities for generic programming in the C++ Standard Library Preview the upcoming concepts feature The companion website, tmplbook.com, contains sample code and additional updates.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值