質問:
C ++の特殊なテンプレート関数から「ベース」テンプレート関数を呼び出す方法はありますか?子クラスがそれらをオーバーライドするときに仮想メソッドの親のバージョンにアクセスできる方法はありますか? (注:答えは「いいえ」だと思いますが、間違っていれば幸いです)
コンテキスト:
テンプレート関数を特殊化しているのは、コードの「内臓」が変わったからではなく、特殊なケースで追加の前処理または後処理が必要なためであることがよくあります。
不自然な例を挙げると:
継承を使用すると、次のことができます。
struct base {
virtual void go() { printf("%p", this); }
};
struct foo : base {
virtual void go() { printf("this foo lives at "); base::go(); }
};
... foo::go() を呼び出すと、「この foo は <アドレス> に住んでいます」と出力されます。
ただし、テンプレートを使用する場合:
template <typename T>
void go(T const &t) { printf("%p\n", &t); }
template <>
void go(foo const &f) {
printf("this foo lives at ");
??? how to access "base" template ???
}
小さなヘルパー関数の混乱を取り除き、実際に気にする関数の代わりにそれらを特殊化することで、醜い方法で問題を回避できます。
template <typename T>
void _go_pre(T const &t) { /* do nothing */ }
template <typename T>
void _go_post(T const &t) { /* do nothing */ }
template <typename T>
void go(T const &t) {
_go_pre(t); /* just in case */
printf("%p\n", &t);
_go_post(t);
}
template<>
void _go_pre(foo const &t) { printf("this foo lives at "); }
...しかし、「ベース」テンプレートは「子」の特殊化がそれをオーバーライドする可能性のあるすべての方法を予測する必要があり、ほとんどのタイプはそれらのフックを使用する場合はほとんど使用しないため、コードが大幅に混乱します。これらのフックの理由は定義された時点では不明であり、使用/未使用のフックのさまざまな組み合わせをテストする必要があるため、クラッターはすぐに判読不能になり、保守できなくなります。
これはすべて、子クラスが親クラスによって提供される元のバージョンにアクセスできない世界で仮想メソッドのオーバーライドで発生する問題とまったく同じです。