模板-1-模板类的特化

类模板的特化

  • 语义: 表明该模板类在特殊的类型下具有不同的行为.

    • 类的定义,应该与模板类放入一个头文件中,告知编译器该特化类的存在;

    • 类成员的定义,应该放入源文件中.该特化类就与普通类一样,是一个实实在在存在的实体.

  • 语法: 仍依'template<>'表明该类是一个模板,但被特化的类;

    • 类外定义特化类的成员时,不应添加'template<>'标记.

template<>
class    类名<特化类的模板实参表>{
    /* 特化类的定义 */
};

  • 对特化类的要求: 类名与模板类一致即可,其余没有任何限制:特化类可以具有不同的成员集合,特化类可以具有不同的父类....

template<typename Type1,typename Type2>
class   X{
public:
    void    print(){ Println("模板类: Type1: %s\tType2: %s",getTypeName(Type1),getTypeName(Type2)); }
};

template<>
class   X<int,double>{
public:
    void    print();
    void    test(){}
};

/* 不要添加'template<>'标记 */
void    X<int,double>::print(){ Println("特化类: Type1: int\tType2: double"); }

int main(int argc,char *argv[]){
    X<double,double>    dd;
    dd.print();
//  dd.test();  /* 错误!X<double,double>不存在test()成员函数. */

    X<int,double>       id;
    id.print();
    id.test();  /* 只要X<int,double>中才存在test()成员函数 */
}

特化成员而不特化类

  • 语义: 表明该模板类在指定的模板实参下,其某些成员具有不同的行为.

  • 语法: 见下面的例子. 

    • 特化成员的声明应该与模板类放在同一个头文件中.

    • 如果成员特化后是一个实实在在的函数,则应该放入源文件中;否则应该放入头文件中.

/* TestTem.h --- 模板类及其布特化成员的声明 */
#define     getTypeName(type)       typeid(type).name()
#define     PrintType(type) Println(#type ": %s",getTypeName(type));

template<typename Type1>
struct TestTem {
    template<typename Type2>
    void    func2();
    void    func1();
};

/* 成员func1的特化声明.此时func1是一个实实在在的函数 */
template<>
void    TestTem<float>::func1();

/* 模板成员func2的特化声明,此时仅特化了一部分.所以特化后的func2仍是模板. */
template<> template<typename Type2>
void    TestTem<float>::func2();

/* 模板成员 func2 的特化声明,此时进行了全部特化,func2也是一个实实在在的函数. */
template<> template<>
void    TestTem<float>::func2<double>();

/* --- TestTem成员定义 ---- */
template<typename Type1>
void    TestTem<Type1>::func1(){
    Println("模板: %s",getTypeName(Type1));
}
template<typename Type1> template<typename Type2>
void    TestTem<Type1>::func2(){
    Println("模板: %s\t%s",getTypeName(Type1),getTypeName(Type2));
}

/* --- 特化函数func2的定义 --- */
template<> template<typename Type2>
void    TestTem<float>::func2(){ Println("1特化: double\t%s",getTypeName(Type2)); }

/* TestTem.cc --- 特化成员的定义 */
/* 成员func1的特化声明.此时func1是一个实实在在的函数 */
template<>
void	TestTem<float>::func1(){ Println("特化: int"); }

/* 模板成员 func2 的特化声明,此时进行了全部特化,func2也是一个实实在在的函数. */
template<> template<>
void	TestTem<float>::func2<double>(){ Println("2特化: float\tdouble"); }

类模板的部分特化

  • 部分特化的类仍然是模板,可以与其特化类具有完全不同的成员集合,父类..

#define		TypeName(type)		typeid(type).name()
#define 	PrintType(type) Println(#type ": %s",TypeName(type));

template<typename Type1,typename Type2,typename Type3>
struct	X{
	void	print(){ Println("模板: %s\t%s\t%s",TypeName(Type1),TypeName(Type2),TypeName(Type3)); }
};

/* 是其模板类模板形参表的子集 */
template<typename Type2>
struct	X<int,Type2,double>{/* 此时 Type1=int,Type3=double */
	void	print(){ Println("特化: i\t%s\td",TypeName(Type2)); }
};

X<double,double,double>    x;    /* 使用模板类,此时 Type1=Type2=Type3=double */
X<int,double,double>    x1    /* 使用部分特化类,此时 Type1=int,Type2=double,Type3=double */


你可能感兴趣的:(模板,模板类,特化)