歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> 讓GCC支持成員函數模板的trick

讓GCC支持成員函數模板的trick

日期:2017/3/1 9:18:12   编辑:Linux編程

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: www.linuxidc.com
*/


#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>)了。

Linux升級GCC 4.8.1清晰簡明教程(Ubuntu 12.04 64位版為例) http://www.linuxidc.com/Linux/2014-04/99583.htm

Ubuntu下Vim+GCC+GDB安裝及使用 http://www.linuxidc.com/Linux/2013-01/78159.htm

Ubuntu下兩個GCC版本切換 http://www.linuxidc.com/Linux/2012-10/72284.htm

CentOS6.5升級手動安裝GCC4.8.2 http://www.linuxidc.com/Linux/2015-01/112595.htm

GCC 的詳細介紹:請點這裡

Copyright © Linux教程網 All Rights Reserved