一、模板函数
#include <iostream> template <typename T> inline T const& max(T const& a, T const& b) { return a < b ? b : a; } template <typename TR,typename T1,typename T2> inline TR add(T1 a, T2 b) { return a + b; } template <typename T1,typename T2> auto sub(T1 a, T2 b)->decltype(a - b) { return a - b; } int main() { std::cout<<::max(5.5,1.3)<<std::endl; //::表示全局名字空间,避免与 std 名>字空间里的 max 方法冲突 std::cout<<::max<int>(5.5,1.3)<<std::endl; //显式限定模板类型 std::cout<<add<int>(5.5,1.3)<<std::endl; //显式指定返回类型,其实与上面一样,是部分显式限定模板类型 std::cout<<sub(5.5,1.3)<<std::endl; //自动推导返回类型 }
在编译时,模板会被编译两次:
第一次是在实例化之前,编译器会检查模板代码的语法问题。
第二次是在实例化期间,编译器会检查是否所有的模板调用都有效(比如实例化类型不支持某些函数的调用等,此 max 例中就是传入的模板实参不支持 operator< 操作)。
模板函数的重载:(包括与普通同名函数与模板特化函数)如果存在重载,优先选择普通函数,其次是特化函数,最后是通用模板函数,由特殊到一般。
类模板的特化和局部特化、缺省模板实参。
template<> class classname<T的特化类型> {...};
template<typename T1> class classname<T2的特化实例> {...};
非类型模板参数的限制:常整数(包括枚举值),或者指向外部链接对象的指针。
模板内部的 typename 表示标识符可以是一个类型。
.template 构造
模板类继承后无法直接调用基类成员,需要使用this->修饰符来访问基类成员
template <typename T> class Base { public: void exit(); }; template <typename T> class Derive:public Base<T> { public: void foo() { this->exit(); //or Base<T>::exit(); } };
使用字符串作为模板参数需要注意:
template <typename T1> template <typename T2> inline T2 const& max (T const& a, T const& b) { return a < b ? b : a; } int main() { std::string s; ::max<std::string>("apple","peach"); // OK: same type char[5] // ::max("apple",s); // ERROR: different types }
成员函数的特化,不能在类里实现特化版本,甚至不能声明,只能在类外实现。
如果在类外特化也不行(可能会在链接时报重定义错误),则放在 .cpp 文件中实现特化版本。
#include <iostream> #include <string> struct User { template<typename T> T print() { std::cout<<"print()"<<std::endl; } //template<> //void print<int>() // std::cout<<"print<int>()"<<std::endl; //} }; template<> int User::print<int>() { std::cout<<"print<int>"<<std::endl; } int main() { User u; u.print<int>(); }
模板非类型参数可以为 int,枚举,指针,函数指针:
如:template<typename T,std::string(*func)(std::string)> class Test{};
参考:http://www.cnblogs.com/Clingingboy/archive/2011/03/08/1977372.html