模板应该是C++语言中最难的部分。从知名的agg图形库,C++标准库Boost,就可以看到C++模板的强大之处。同时也看到模板存在的一些问题:
-
不当的使用会造成最终的二进制代码膨胀。
-
过度使用模板,导致代码易读性不好,并且调试困难。
-
工程中过多模板,造成工程构建速度奇慢无比。
在vc6时代,我个人一直对C++模板编程都是敬而远之,但随着越来越多的编译器对C++标准支持的越来越好,我也逐渐开始尝试在开发中适当的使用模板,毕竟它可以减少大量重复的代码,提高生产效率。尤其是在编写基础类库时,更能发挥其威力。
今天一时兴起,想在模板类中使用的成员模板函数输出模板参数的值,便随手写了下面一个类:
template <typename TYPE> class TestClass { public: // 其他成员函数 // ...... template <typename Ty> void Print(const Ty& td) { printf("common type\n"); } template <> void Print<int>(const int& td) { printf("int:%d\n", td); } template <> void Print<double>(const double& td) { printf("double:%lf\n",td); } }; int main(int argc, const char * argv[]) { TestClass<bool> tx; tx.Print(4); tx.Print(4.01); tx.Print(4.0f); return 0; }
这段代码在vs2013上编译运行,一切正常。但是在xcode上发现编译报错。网上百度之后也没解决我的问题,没办法只能去查C++白皮书。研究之后发现发现上面的代码存在以下两个问题:
-
成员模板函数特化不能实现在类的声明中,只能在类的外部实现。
-
不能特化没有明确特化的模板类的成员函数。
C++标准中明确规定,当一个模板类没有明确特化时,不能特化其中的成员模板函数,或嵌套的内部模板类。所以正确的代码如下:
template <typename TYPE> class TestClass { public: // 其他成员函数 // ...... template <typename Ty> void Print(const Ty& td) { printf("common type\n"); } }; template <> template <> inline void TestClass<bool>::Print<int>(const int& td) { printf("int:%d\n", td); } template <> template <> inline void TestClass<bool>::Print<double>(const double& td) { printf("double:%lf\n",td); }
由于多平台编译的需要,上面的代码在GCC,LLVM,MSVC编译器都验证通过。
模板存在诸多问题,被好多人所诟病 ,所以模板又被称之为C++语法糖。既然是糖,那说明还是可以吃的,当然吃多了 对牙齿有害。一句话,模板可以适当使用 ,但不要过度使用,也不要刻意回避。学会扬长避短 ,发挥它的优势才是王道。