讓gcc支持成員函數(shù)模板的trick
羅朝輝 (http://www.shnenglu.com/kesalin/)
gcc 4.7.3 不支持成員函數(shù)模板特化。如下代碼:
#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 中編譯運(yùn)行是沒(méi)有問(wèn)題的,但在 gcc 4.7.3下,編譯都通不過(guò):
../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’
為了達(dá)到近似成員函數(shù)模板特化的效果,可以利用成員函數(shù)主模板以及重載函數(shù)來(lái)實(shí)現(xiàn):
/*
* 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_ */
調(diào)用 DoTest() 運(yùn)行結(jié)果如下:
Primary template DummyIdentity<T>

.
overload function
for DummyIdentity<
int>

.
overload function
for DummyIdentity<Base *>

.
Primary template DummyIdentity<T>

.
注意:
VS2010 版本的代碼,模板形參為 T,在實(shí)例化不會(huì)進(jìn)行隱式類(lèi)型轉(zhuǎn)換。即用 Derived * 當(dāng)作實(shí)參調(diào)用的是主模板,而不是 Base * 特化版本
而在 gcc 下,模板形參雖然也為T(mén),但影響重載決議的 function 參數(shù)為:DummyIdentity<T>,用不同的實(shí)際參數(shù)實(shí)例化該模板,得到的是一堆重載函數(shù)。因此用 Derived * 當(dāng)作實(shí)參時(shí),調(diào)用的函數(shù)自然就是實(shí)例化的 void function(DummyIdentity<T>)了。