Variadicテンプレートとダイナミックキャスト
-
27-10-2019 - |
質問
次のようにC ++コードの一部があります:
template <typename ...A>
struct CastAll{
template <typename ...B>
void cast_all(void(*fun)(B...), A...as){
//...
}
};
私がやりたいのは、cast_allを実装して、それぞれの引数をそれぞれのそれぞれをBのそれぞれのタイプに動的にし、「キャストされた」引数で与えられた関数を楽しく呼ぶようにすることです。
たとえば、in:
struct A{};
struct B : public A{};
void foo(B *b1, B *b2){
//... does something with b1 and b2
}
int main(){
A *a1 = new B();
A *a2 = new B();
CastAll<B*, B*> cast; //used to cast each A* to B*
cast.cast_all<B*, B*>(foo, a1, a2);
}
cast_allは次のようなものに拡張する必要があります:foo(dynamic_cast(a1)、dynamic_cast(a2));
Variadicテンプレートに関する多くの記事を見ました。しかし、数時間後、私はまだそれを理解することができません。
何か案は?
解決
単に
template <typename ...A>
struct CastAll{
template <typename ...B>
void cast_all(void(*fun)(B...), A...as){
fun(dynamic_cast<B>(as)...);
}
};
動作するはずであり、GCCのコピーで機能します。ただし、サンプルコードのいくつかの変更が必要です。 A
多型である必要があります(これは作るでしょう B
順番に多型) dynamic_cast
可能性があります(例コードで慣習的であるように、仮想、デフォルトのデストラクタを追加しました)。そして、あなたはおそらく使用するつもりでした CastAll
なので:
CastAll<A*, A*> cast;
cast.cast_all(foo, &a1, &a2);
つまり、あなたが渡す議論 cast_all
ポインターです A
その後、ダウンキャストされます B
体の中。さらに、テンプレートパラメーターの一部が推定されます1.
これは、いくつかのパラメーターパックを使用することが許可されているために機能します(ここでは、 A
と B
)1つのパック拡張(ここで、 dynamic_cast
)、それらが同じサイズを持っている場合。それ以外の場合は、Sfinaeによるサイレントエラーです。 N3290、14.5.3/5 Variadicテンプレート[Temp.Variadic]:
- ...]パック拡張のパターンは、ネストされたパック拡張によって拡張されない1つ以上のパラメーターパックに名前を付けます。このようなパラメーターパックは、パターン内の未装飾パラメーターパックと呼ばれます。パック拡張によって拡張されたすべてのパラメーターパックには、指定された同じ数の引数があります。 [...
1: :ここで控除が許可されているかどうかについての決定的な参照を見つけることができません。 GCCは、私がターンすると両方のパックを推測することさえできます CastAll
多型ファンチャーに。これが義務付けられている行動である場合、私はやや疑わしいですが、少なくともあなたはとにかく非定義の議論を指定する方法を知っているようです。
他のヒント
編集]ゼロから書き直します。このようなものは可能であるべきですが、私はコンパイラにacecsを持っていません。 いいえ それはもはや必要ではないので、終わりになります。これは、少なくとも1つのパラメーターを渡さないと失敗しますが、それを問題とは見ていませんでした。
template<typename...BL>
struct Recast {
template <typename B, typename ...BR>
struct Inner {
template <typename A, typename ...AR>
static void cast_all(void(*fun)(BL...,B,BR...), BL... al, A a, AR... ar) {
Recast<BL..., B>::template Inner<BR...>::cast_all<AR...>(fun, al..., dynamic_cast<B>(a), ar..);
}
};
template <typename B>
struct Inner<B> {
template <typename A>
static void cast_all(void(*fun)(BL...,B), BL... al, A a) {
fun(al..., dynamic_cast<B>(a));
}
};
};
template <typename ...BR> //note I switched these
struct CastAll{
template <typename ...AR> //note I switched these
static void cast_all(void(*fun)(BR...), AR...ar){
Recast<>::template Inner<BR...>::cast_all(fun, ar...);
}
};
struct A{};
struct B : public A{};
void foo(B *b1, B *b2){
//... does something with b1 and b2
}
int main(){
A *a1 = new B();
A *a2 = new B();
CastAll<B*, B*>::cast_all(foo, a1, a2);
}
ideone.comが報告したように、私はまだ理解できないエラーがあることを認めます
prog.cpp:staticメンバー関数 'static void recast :: inner :: cast_all(*)(bl ...、b、br ...)、bl ...、a、ar ...)' :
prog.cpp:7:39:エラー:「...」トークンの前に予想される一次表現
prog.cpp:7:39:エラー:queedt ';' 「...」トークンの前