讓gcc支持成員函數模板的trick
讓gcc支持成員函數模板的trick
羅朝輝 (http://www.rzrgm.cn/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: explicit specialization in non-namespace scope ‘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>)了。
浙公網安備 33010602011771號