関数テンプレートのtrick


関数テンプレートのtrick
gccにメンバー関数テンプレートのtrickをサポートさせる
羅朝輝(http://www.cnblogs.com/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....
"); } template<> void function<int>(){ printf(" Specialization for int....
"); } template<> void function<Base *>() { printf(" Specialization for Base *....
"); } }; class Tester { public: static void DoTest() { Functor functor; functor.function<char>(); functor.function<int>(); functor.function<Base *>(); functor.function<Derived *>(); } }; #endif // __MEMFUNTEMPLATE_H__


 
VS 2010でのコンパイル運転は問題ないが、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>....
"); } void function(DummyIdentity<int>) { printf(" overload function for DummyIdentity<int>....
"); } void function(DummyIdentity<Base *>) { printf(" overload function for DummyIdentity<Base *>....
"); } }; 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>....

 
注意:
VS 2010バージョンのコードは、テンプレートパラメータがTであり、インスタンス化では暗黙的なタイプ変換は行われません.つまり、Derived*を実パラメータとして呼び出したのは、Base*特化バージョンではなくメインテンプレートです.
一方,gccではテンプレートパラメータもTであるが,重荷決定に影響するfunctionパラメータはDummyIdentityであり,このテンプレートを異なる実際のパラメータでインスタンス化し,重荷関数の山を得た.したがって,Derived*を実パラメータとして用いる場合,呼び出される関数は当然インスタンス化されたvoid function(DummyIdentity)である.
 
 
 
分類:
C/C++
ラベル:
C++
gcc
template