C++ 模板

  • 模板形参可以是Type parameter,也可以是NonType parameter
  • 模板实例化在编译阶段,因此Type parameter需要在编译阶段就确定,同样地NonType parameter也需要在编译阶段确定具体值
  • 内联inline 需要放在模板形参表之后,
template <typename T> inline T min(const T&, const T&)
  • 模板函数的非类型模板形参
    • 模板函数的模板形参可以是具体的值,实例化时使用具体的值来代替非类型模板形参。
    • 模板非类型形参是模板定义内部的常量值
template <class T, size_t N> void array_init(T (&para)[N])//(& para)[N]表示此函数传递的是数组的引用,此时对实参的要求是类型和个数都要符合形参的定义
{
    for(size_t i=0; i!=N; ++i)
    {
        para[i] = 0;
    }
}

int x[42];
double y[10];
array_init(x);//x在编译阶段是确定的,表示int类型,含有42个元素的数组
array_init(y);//y在编译阶段是确定的,表示double类型,含有10个元素的数组
//由于数组元素个数在编译阶段确定,因此x和y即表示类型同时还表示数组的元素个数
  • 类模板的非类型形参可以作为不同实例化时的内部常量使用
template <int hi, int wid>
class Screen{
public:
    //template nontype parameters used to initialize data members
    Screen():screen(hi*wid, '#'), cursor(0), height(hi), width(wid){}
    // ...
private:
    std::string screen;
    std::string::size_type cursor;
   std::string::size_type height, width;             
};

  • 可以使用函数模板对指向函数的指针赋值
template <typename T> int compare(const T&, const T&);
int (*pf1) (const int&, const int&) = compare;
  • 模板编译模型,因为编译模板时需要做模板实例化,而实例化过程需要知道模板的定义。而一般的编程习惯是模板的声明放在头文件里面,模板的定义放在源文件里面,而调用模板出通常是会include头文件。但是如果不建立模板声明与模板定义之间的关联,模板实例化就不能够成功。标准C++为编译代码提供两种类型
    • 包含编译模型,即在模板声明的头文件里面include模板定义的源文件,这样做可以保证调用模板实例化时可以找到模板定义
//header file utlities.h
#ifndef UTLITIES_H
#define UTLITIES_H
template<class T> int compare(const T&, const T&)
//other declarations

#include "utlities.cc" //get the definitions for compare etc
#endif

//implementation file utlities.cc
template <class T> int compare(const T&, const T&)
{
    if(v1<v2) return -1;
    if(v2<v1) return 1;
    return 0;
}
  • 分别编译模型,在模板定义出加上export关键字,对于export关键字修饰的模板定义,编译器会主动查找
//the template definition goes in a separately-compiled source file
export template <typename Type>
Type sum(Type t1, Type t2)

//对于类模板而言,应该在类的实现文件中使用export,因为如果在头文件中则可能头文件include多次,多个export
//class template header goes in shared header file
template <class Type> class Queue{ ... };
//Queue.cc implementation file declares Queue as exported
export template <class Type> class Queue;
#include "Queue.h"
//Queue member definitions
  • 类模板中的友元声明
    • 普通非模板类或者函数的友元声明,将友元关系授予明确指定的类或函数
template <class Type> class Bar{
    //Grants access to ordinary, nontemplate class and function
    friend class FooBar;
    friend void fcn();
    //...
}

  • 类模板或函数模板的友元声明,授予对友元所有实例的访问权
template <class Type> class Bar{
    //grants access to Foo1 or templ_fcn1 parameterized by any type
    template <class T> friend class Foo1;
    template <class T> friend void templ_fnc1(const T&);
    //lll
}
  • 只授予对类模板或者函数模板的特定实例的访问权的友元声明
template <class T> class Foo2;
template <class T> void templ_fcn2(const T&);
template <class Type> class Bar{
    //grants access to a single specific instance parameterized by char*
    friend class Foo2<char*>;
    friend void templ_fcn2<char*>(char* const &);
    //...
}
  • 类模板的static成员
    • 用一个推导结果的实例的共享static,不同推导结果的不共享static,会存在另一个static
  • 函数模板特化
    • 特化与通用是相对的,特化就是通用的模板定义不能够再适用,为某些特殊的类型特化一个模板定义
    • 如下代码,const char*类型的模板不能够再使用通用的大于号,小于号来比较,所以需要特化
//special version of compare to handle C-style character strings
template<>
int compare<const char*>(const char* const &v1, const char* const &v2)
{
    return strcmp(v1, v2);
}

const char *cp1 = "world", *cp2 = "hi",
int i1, i2;
compare(cp1, cp2);//call the specialization
compare(i1, i2);//call the generic version instantiated with int
  • 类模板特化
    • 可以特化类整体,也可以特化成员,以及可以针对部分类型形参做特化
      类整体特化,类的函数定义在源文件中,不必再添加特化标记template<>
template<> class Queue<const char*>{
public:
    void push(const char*);
    void pop() {real_queue.pop}
    bool empty() const {return real_queue.empty();}   
    std:string front() {return real_queue.front();}
    std::string front() {return real_queue.front();}
    const std::string &front() const {return real_queue.front();}
private:
    Queue<std::string> real_queue;// forward calls to real_queue    
}
  • 类成员特化,部分成员的特化可以看做是模板函数的特化
template<>
void Queue<const char*>::pop()
{
    //...
}
  • 部分形参特化
template <class T1, class T2>
class some_template{
    //...
};
//partial specialization:fixes T2 as int and allows T1 to vary
template<class T1>
class some_template<T1, int>
{
    //....
};
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值