2011-06-29 11 views
2

私は、次のような何かをしたい型以外のテンプレート引数としてローカル変数

Example(&Class::MemberFunction, this)); 

//... 

template<class T_CLASS> 
inline static void Example(void (T_CLASS::*MemberFunctionPointer)(), T_CLASS* InstancePointer) 
{ 
    SomeClass<T_CLASS>::Bind<MemberFunctionPointer>(InstancePointer); 
} 

しかし、私はエラーを取得:*テンプレートパラメータ「T_MEMBER_FUNCTION」:「MemberFunctionPointer」:ローカル変数を使用することはできませんこの問題のための*

非型引数として任意のソリューション?私は、ミルコを

感謝を「バインド」を呼び出すための簡単な方法を提供したい

//編集:

私はMemberFunctionPointerは私が再び必要とする「バインド」であるため非型テンプレートパラメータになりたいですそれはテンプレート引数として。 あなたはあなたの答えに書いたように、私の場合にはMemberFunctionPointerは可変であり、その値は、コンパイル時には不明です。しかし、MemberFunctionPointerは常に同じ関数を指しています。例えば、コンパイラがコンパイル時にそれを知るように定数を作る方法はありますか?

+0

この非常によく似た質問を見てくださいhttp://stackoverflow.com/q/6041570 – sharptooth

答えて

0

MemberFunctionPointerは、したがって、あなたが必要なものを、使用することはできません、変数ではないタイプ(またはコンパイル時定数)でこのようなものが良いかもしれ、その関数の実署名..です

template<typename T_FUNC_PTR, class T_CLASS> 
inline static void Example(T_FUNC_PTR fPtr, T_CLASS* InstancePointer) 
{ 
    SomeClass<T_CLASS>::Bind<T_FUNC_PTR>(fPtr, InstancePointer); 
} 

つまり、コンパイラは関数ポインタ(注:あなたがあまりにも関数へのポインタを伝播する必要があります)の種類を推測させ

Example(&foo::bar, foo_inst); 

を呼び出すようにすると、これは非常に、テストされていないと私の頭の上からで、構文少しオフにすることができ...

編集:ここでは、概念を実証するためのシンプルな例です:

#include <iostream> 
struct foo 
{ 
    void bar() { std::cout << "foo::bar()" << std::endl; } 
}; 

template<typename T_FUNC_PTR, typename T_CLASS> 
void exec(T_FUNC_PTR ptr, T_CLASS& inst) 
{ 
    (inst.*ptr)(); 
} 

int main(void) 
{ 
    foo inst; 
    exec(&foo::bar, inst); 
} 
+0

最初の文では、テンプレートパラメータ。本当じゃない。 C++のテンプレートシステムも非型パラメータを受け入れます。しかし、これらは整数型のコンパイル時*定数か、外部リンケージを持つものへのポインタ/参照でなければなりません。 – sellibitze

+0

@sellibitze、本当ですか?私は変数が変数であり型ではないことを明示しています...私はもう少し明示的になるでしょう... – Nim

+0

返信ありがとうございます。上で説明したように、メンバ関数ポインタを非型テンプレート引数にしたい。私の "Bind"呼び出しのように渡すときは問題ありませんが、テンプレートパラメータを取らないラッパー関数 "Example"を使いやすくしたいと思います。例では、MemberFunctionPointerをパラメータとして取得し、非型テンプレートパラメータとして「Bind」に渡す必要があります。それは常に同じ関数を指していて、私はコンパイル時にそれをコンパイラーに知らせたいのです。これは可能ですか? – Mirco

4

テンプレートのパラメータが可能なものの二種類があります:タイプとコンパイル時定数式が 。関数のパラメータの内容は、コンパイル時に決定可能な値ではありません。したがって、コンパイラはそれに基づいてテンプレートをインスタンス化することはできません。

注意:テンプレートはタイプです。型はコンパイル時に決定可能でなければなりません。

おそらくBind関数の引数としてメンバーポインタを渡す必要があります。

1

私はあなたが達成しようとしている何をかなり確実ではないのですか?

MemberFunctionPointerが変数の場合、その値はコンパイル時には不明であり、たとえば一部のユーザーの動作に依存する可能性があるため、テンプレート引数として使用することはできません。

コンパイル時にMemberFunctionPointerを実際に導き出すことができる場合は、関数パラメータの代わりにテンプレート引数として渡す必要があります。次の例を考える:

(最初のケースではBindcallを使用し、第二の場合に、StaticBindcallStaticを使用)

#include <stdio.h> 

class X { 
    public: 
    int x; 
    void foo() {printf("foo\n");} 
    void bar() {printf("bar\n");} 
}; 

template <typename T> 
class SomeClass { 
    public: 
    static void Bind(void (T::*MemberFunctionPointer)(), T *obj) { 
     (obj->*MemberFunctionPointer)(); 
    } 
    template <void (T::*MemberFunctionPointer)()> 
    static void StaticBind(T *obj) { 
     (obj->*MemberFunctionPointer)(); 
    } 
}; 

template <class C> 
static inline void call(void (C::*MemberFunctionPointer)(), C *obj) { 
    SomeClass<C>::Bind(MemberFunctionPointer,obj); 
} 

template <class C, void (C::*MemberFunctionPointer)()> 
static inline void callStatic(C *obj) { 
    SomeClass<C>::template StaticBind<MemberFunctionPointer>(obj); 
} 

int main() { 
    X obj; 
    call<X>(&X::foo,&obj); 
    callStatic<X,&X::bar>(&obj); 
    return 0; 
} 
+0

私はそれをコンパイル時に演繹したいと思っていますが、私はどのようにして分かりません。だから、2番目のケースは良くフィットします...私はテンプレート引数を取らないメソッド "call"を提供しようとします。 – Mirco

+0

その場合、実際には最初のメソッドとインラインのすべての関数を使用できます。しかし、この例で示すように、Bind関数は、テンプレートパラメータではなく、パラメータによってメンバ関数ポインタを取らなければなりません。最適化がオンになっていると、定数に沸騰し、実行時オーバーヘッドが発生しません。関数 'call'のテンプレート' 'は、渡されたパラメータから実際に推測することができるので、実際に呼び出しでスキップすることができます。わかりやすくするために私はそこにそれを与えた。 – CygnusX1

1

テンプレートパラメータは、コンパイル時に知られなければなりません。関数のパラメーターであるポインター変数の内容は、この関数の呼び出し方法によって異なります。これはコンパイル時にはわかりません!

すでにコンパイル時にこのポインタを知っている場合、あなたはテンプレートパラメータに関数ポインタのランタイムパラメータを変えることができます:ここでは

template<class T_CLASS, void(T_CLASS::*MemFunPtr)()> 
void Example(T_CLASS* InstancePointer) {...} 

、MemFunPtrはコンパイル時に知られているテンプレートのパラメータであり、他の関数またはクラステンプレートのテンプレートパラメータとして再利用することができます...

+0

ありがとう、それは私がしたいことです。あなたが理解しているように、MemFunPtrを通常のパラメータとして渡し、それをテンプレートパラメータとしてExampleに渡すことは避けられますか? – Mirco

+0

はい、そうです。 – sellibitze

関連する問題