让gcc支持成员函数模板的trick

Posted 飘飘白云

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了让gcc支持成员函数模板的trick相关的知识,希望对你有一定的参考价值。

让gcc支持成员函数模板的trick

罗朝辉 (http://blog.csdn.net/kesalin/)

本文遵循“ 署名-非商业用途-保持一致”创作公用协议   gcc 4.7.3 不支持成员函数模板特化。如下代码:
#ifndef __MEMFUNTEMPLATE_H__ #define  __MEMFUNTEMPLATE_H__
#include <stdio.h>
class  Base ; class  Derived : public  Base ;
struct  Functor      template <typename T>  void  function()          printf(" Primary template .\\n");    
    template<>      void  function< int >()         printf(" Specialization for int .\\n");    
    template<>  void  function<Base *>()          printf(" Specialization for Base * .\\n");     ;
class  Tester  public :      static   void  DoTest()             Functor functor;         functor.function< char >();         functor.function< int >();         functor.function<Base *>();         functor.function<Derived *>();     ;
#endif   //  __MEMFUNTEMPLATE_H__

在 VS2010 中编译运行是没有问题的,但在 gcc 4.7.3下,编译都通不过:

../src/MemFunTemplate.h:21:14: error: <strong> explicit specialization  in non- namespace scope</strong> ‘ struct Functor’ ../src/MemFunTemplate.h:22:24: error: template-id ‘function< int>’  in declaration of primary template ../src/MemFunTemplate.h:26:14: error:  explicit specialization  in non- namespace scope ‘ struct Functor’ ../src/MemFunTemplate.h:26:38: error: template-id ‘function<Base*>’  in declaration of primary template ../src/MemFunTemplate.h:26:21: error: ‘ void Functor::function()’ cannot be overloaded ../src/MemFunTemplate.h:22:10: error: with ‘ void Functor::function()’ ../src/MemFunTemplate.cpp: In function ‘ int main()’: ../src/MemFunTemplate.cpp:17:2: error: ‘DoTest’  is not a member of ‘Functor’


为了达到近似成员函数模板特化的效果,可以利用成员函数主模板以及重载函数来实现:


/*  * MemFunTemplate.h  *  *  Created on: Jul 12, 2013  *      Author:  http://blog.csdn.net/kesalin/  */
#ifndef MEMFUNTEMPLATE_H_ #define  MEMFUNTEMPLATE_H_ #include <stdio.h> template<typename T> struct  DummyIdentity      typedef T type; ; class  Base ; class  Derived : public  Base ; struct  Functor      template <typename T>  void  function()          function(DummyIdentity<T>());     private :     template <typename T>      void  function(DummyIdentity<T>)          printf(" Primary template DummyIdentity<T> .\\n");          void  function(DummyIdentity< int >)          printf(" overload function for DummyIdentity<int> .\\n");          void  function(DummyIdentity<Base *>)          printf(" overload function for DummyIdentity<Base *> .\\n");     ; class  Tester  public :      static   void  DoTest()             Functor functor;         functor.function< char >();         functor.function< int >();         functor.function<Base *>();         functor.function<Derived *>();     ; #endif  /* MEMFUNTEMPLATE_H_ */


调用 DoTest() 运行结果如下:

 Primary template DummyIdentity<T> .  overload function  for DummyIdentity< int> .  overload function  for DummyIdentity<Base *> .  Primary template DummyIdentity<T> .


注意:

VS2010 版本的代码,模板形参为 T,在实例化不会进行隐式类型转换。即用 Derived * 当作实参调用的是主模板,而不是 Base * 特化版本

而在 gcc  下,模板形参虽然也为T,但影响重载决议的 function 参数为:DummyIdentity<T>,用不同的实际参数实例化该模板,得到的是一堆重载函数。因此用 Derived * 当作实参时,调用的函数自然就是实例化的 void function(DummyIdentity<T>)了。

以上是关于让gcc支持成员函数模板的trick的主要内容,如果未能解决你的问题,请参考以下文章

虚函数和虚拟继承的内存分布

GCC C++14/17 成员函数指针模板参数的区别

为啥我不能从 gcc 中的前身模板化成员函数访问祖先方法?

C++之:虚函数表

C++ 模板函数重载决议

C++模板详解