- メソッド(=メンバ関数)ポインタのテンプレートパラメータパックを作成できますか?
- 「はい」の場合は、テンプレートパラメータパックのすべてのメソッドを実行する(テンプレート)関数を作成できますか?
簡略化:テンプレートパラメータパックが指すすべてのメソッドを実行する
- 尖ったメソッドの実行の順序は重要ではありません。
- すべてのメソッドポインタは、同じシグネチャを持っている(例えば
bool
を返し、同じ基本クラスを持って、引数を取りません)
簡略化:テンプレートパラメータパックが指すすべてのメソッドを実行する
bool
を返し、同じ基本クラスを持って、引数を取りません)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,
をオーバーロードする型を返す可能性に対処する必要があります。
ありがとうございました。ただし、テンプレートはメソッドポインタのパラメータパックを使用していません。 – ManuelAtWork
@ManuelAtWorkメソッドポインタを渡しています。これらの引数の型はメソッドポインタです。だから彼らは...メソッドポインタのパラメータパックです。まさに、メソッドポインタのパラメータパックではないのですか?あなたは*他のタイプが受け入れられるかもしれないことを意味しますか?trueですが、 ' - > *'をオーバーライドした場合にのみコンパイルされます。その場合、なぜ気にしますか? – Yakk
すべてのテンプレートパラメータパックは、 '' 'class ...' ''で始まり、** type **のパラメータパックになります。 C++標準では、整数やポインタなどの非型テンプレートパラメータも使用できます。メソッドポインターを渡していますが、テンプレートパラメーターではなく、関数パラメーターとして渡しています。私の質問があいまいであれば申し訳ありません。 – ManuelAtWork
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からの寄与)
私の答えからパックの展開を盗み、ゼロ引き終了バージョンを取り除き、再帰を取り除いてください。最初のもの、 'disard'のものは' t'を 'this'と置き換え、' ms'は 'ptrs'で置き換えて' template
@Yakkとしました。再帰のないアプローチをありがとう! – ManuelAtWork
ダブルアンダースコアで始まるシンボルは実装によって予約されています。標準/システムヘッダファイルのスタイルを模倣しないでください。それらは許可されており、場合によってはそのスタイルを使用する必要があります。 – Yakk
はい、はい。試しましたか ? :) – Quentin
@クエンティン:はい、私は、今まで成功しなかった。私に例を教えてもらえますか?私はまだWeb上の例を見つけていない。 – ManuelAtWork
試してみることができますか?あなたの試行が表示されない場合は、エラーがどこにあるかを示すことはできません。 – max66