IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    C++模板,判断是否存在成员函数,实现差异化操作

    天下发表于 2016-01-15 07:01:00
    love 0
    工作中遇到一个问题,我有一个容器,装着各式各样的对象的指针,需要把拥有dump方法的指针内容dump出去,而对于没有dump方法的对象,直接忽略。

    首先想到的是给每个对象提供一个查询操作,从而得知是否拥有dump方法。显然这个方法不能让人满意,需要更改大量的class实现。C++如果我能自动判断某个类型是否拥有某方法,这个问题可以完美的解决,因为是否含有某方法编译期已经确定了,所以是有可能通过一些技巧来实现这个功能的。

    查阅了大量的模板偏特化,匹配失败不是错误,终于找到了Mr.Right:
    废话不多说,贴代码:

    检测是否有定义  void hello():
    点击(此处)折叠或打开
    template<typename T>
    struct has_hello{
        template<typename U, void (U::*)()> struct HELPS;
        template<typename U> static char Test(HELPS<U, &U::hello>*);
        template<typename U> static int Test();
        const static bool Has = sizeof(Test<T>(0)) == sizeof(char);
    }
    测试:
    点击(此处)折叠或打开
    struct A
    {
      void hello(){
        cout<<"A is Hello."<<endl;
      }
      int x;
    };


    int main()
    {
      cout<<"A has hello? "<<has_hello<A>::Has<<endl;
    }

     has_hello 能编译通过,而且能工作!!!

    解释:
    template<typename U> static int Test(); 能匹配所有的类型U
    template<typename U, void (U::*)()> struct HELPS; 当Type U有hello,且hello的类型为 void (U::*)()时,模板HELPS<U, &U::hello>能正确匹配,否则模板无法匹配

    Test<T>(0)  优先匹配 HELPS<U, &U::hello> 因为template<typename U> static char Test(HELPS<U, &U::hello>*) 是一个特化
    sizeof操作符不需要计算表达式的值,是一个编译期的操作,定义指针类型可以只有声明没有定义
    所以HELPS和Test都不需要实现,仅有声明就可以通过编译

    巧妙的探测了自定义类型A是否含有void U::hello() 方法。


    转自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=17286628&id=4643663


    天下 2016-01-15 15:01 发表评论


沪ICP备19023445号-2号
友情链接