录十六

持之以恒

模板类的成员模板函数的特化

模板应该是C++语言中最难的部分。从知名的agg图形库,C++标准库Boost,就可以看到C++模板的强大之处。同时也看到模板存在的一些问题:

  1. 不当的使用会造成最终的二进制代码膨胀。

  2. 过度使用模板,导致代码易读性不好,并且调试困难。

  3. 工程中过多模板,造成工程构建速度奇慢无比。

在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++语法糖。既然是糖,那说明还是可以吃的,当然吃多了 对牙齿有害。一句话,模板可以适当使用 ,但不要过度使用,也不要刻意回避。学会扬长避短 ,发挥它的优势才是王道。

  • 评论列表:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

Copyright © 1999-2019, lu16.com, All Rights Reserved