2
  1. メソッド(=メンバ関数)ポインタのテンプレートパラメータパックを作成できますか?
  2. 「はい」の場合は、テンプレートパラメータパックのすべてのメソッドを実行する(テンプレート)関数を作成できますか?

簡略化:テンプレートパラメータパックが指すすべてのメソッドを実行する

  • 尖ったメソッドの実行の順序は重要ではありません。
  • すべてのメソッドポインタは、同じシグネチャを持っている(例えばboolを返し、同じ基本クラスを持って、引数を取りません)
+4

はい、はい。試しましたか ? :) – Quentin

+0

@クエンティン:はい、私は、今まで成功しなかった。私に例を教えてもらえますか?私はまだWeb上の例を見つけていない。 – ManuelAtWork

+2

試してみることができますか?あなたの試行が表示されない場合は、エラーがどこにあるかを示すことはできません。 – max66

答えて

2
template<class T, class...Ms> 
void run_all(T* t, Ms&&... ms) { 
    using discard=int[]; 
    (void)discard{0,(void(
    (t->*ms)() 
),0)...}; 
} 

用途:

struct foo { 
    bool t1() { return true; } 
    bool t2() const { return false; } 
}; 
int main() { 
    foo f; 
    run_all(&f, &foo::t1, &foo::t2); 
} 

run_allが鈍角であるが、それはあります我々はC++を持っていないから17。

ビット単純な、あるいはある
template<class T, class...Ms> 
void run_all(T* t, Ms&&... ms) { 
    ((void)((t->*ms)()),...); 
} 

template<class T, class...Ms> 
void run_all(T* t, Ms&&... ms) { 
    ((t->*ms)(),...); 
} 

正気の型を返すt->*msに依存しています。

我々はまた、msを返すブール値とはやるという事実に頼ることができる:0メソッドを渡すこれらの全てが順番に彼らの方法を実行すること

template<class T, class...Ms> 
void run_all(T* t, Ms&&... ms) { 
    (void)std::initializer_list<bool>{(t->*ms)()...}; 
} 

または

template<class T, class...Ms> 
void run_all(T* t, Ms&&... ms) { 
    using discard=bool[]; 
    (void)discard{false,(t->*ms)()...}; 
} 

注意とサポート。

上記のvoidの中には、未使用の値の警告をブロックするものがあります。

その他の点では、コールがoperator,をオーバーロードする型を返す可能性に対処する必要があります。

+0

ありがとうございました。ただし、テンプレートはメソッドポインタのパラメータパックを使用していません。 – ManuelAtWork

+0

@ManuelAtWorkメソッドポインタを渡しています。これらの引数の型はメソッドポインタです。だから彼らは...メソッドポインタのパラメータパックです。まさに、メソッドポインタのパラメータパックではないのですか?あなたは*他のタイプが受け入れられるかもしれないことを意味しますか?trueですが、 ' - > *'をオーバーライドした場合にのみコンパイルされます。その場合、なぜ気にしますか? – Yakk

+0

すべてのテンプレートパラメータパックは、 '' 'class ...' ''で始まり、** type **のパラメータパックになります。 C++標準では、整数やポインタなどの非型テンプレートパラメータも使用できます。メソッドポインターを渡していますが、テンプレートパラメーターではなく、関数パラメーターとして渡しています。私の質問があいまいであれば申し訳ありません。 – ManuelAtWork

1
class MyClass { 

    /* The methods to be executed: */ 

    bool func_1() const { /* ... */ } 
    bool func_2() const { /* ... */ } 
    // ... 


    /* The parameter pack expansion: */ 

    typedef bool (MyClass::*FuncPtr)() const; 

    template<class T = void> 
    void Expand() const {} // Termination version. 

    template<FuncPtr ptr, FuncPtr ... Args> 
    void Expand() const { 
    (this->*ptr)(); 
    Expand<Args...>(); 
    } 


    /* The function that calls them all: */ 

    void RunAll() const { 
    Expand< 
     &MyClass::func_1, // <-- input to parameter pack 
     &MyClass::func_2 
    >(); 
    } 

}; 

代替再帰なしのバージョン:

class MyClass { 

    /* The methods to be executed: */ 

    bool func_1() const { /* ... */ } 
    bool func_2() const { /* ... */ } 
    // ... 


    /* The parameter pack expansion: */ 

    typedef bool (MyClass::*FuncPtr)() const; 

    template<typename ... T> void ignore(T && ...) {} 

    template<FuncPtr ... Args> 
    void Expand() const { 
    ignore(((this->*Args)(),0) ...); 
    } 

    /* The function that calls them all: */ 

    void RunAll() const { 
    Expand< 
     &MyClass::func_1, // <-- input to parameter pack 
     &MyClass::func_2 
    >(); 
    } 

}; 

(@Yakkからの寄与)

+0

私の答えからパックの展開を盗み、ゼロ引き終了バージョンを取り除き、再帰を取り除いてください。最初のもの、 'disard'のものは' t'を 'this'と置き換え、' ms'は 'ptrs'で置き換えて' template ' – Yakk

+0

@Yakkとしました。再帰のないアプローチをありがとう! – ManuelAtWork

+0

ダブルアンダースコアで始まるシンボルは実装によって予約されています。標準/システムヘッダファイルのスタイルを模倣しないでください。それらは許可されており、場合によってはそのスタイルを使用する必要があります。 – Yakk

関連する問題