わかりました、これは少し複雑ですので、ご容赦ください。:)
この単純なクラス階層があります。
class A {};
class DA : public A {};
class DDA : public DA {};
そして、これらのクラスで動作する次の関数があります。
void f(A x) {
std::cout << "f A" << std::endl;
}
void f(DA x) {
std::cout << "f DA" << std::endl;
}
void f(DDA x) {
std::cout << "f DDA" << std::endl;
}
次に、DA を少し異なる方法で処理する別の関数を追加します。
(1) 最初の試行は次のようになります。
void g(A t) {
std::cout << "generic treatment of A" << std::endl;
std::cout << "called from g: ";
f(t);
}
void g(DA t) {
std::cout << "special treatment of DA" << std::endl;
std::cout << "called from g: ";
f(t);
}
しかし、これを各クラスのオブジェクトで呼び出しても、明らかに望ましい効果はありません。
電話:
A a; DA b; DDA c;
g(a); g(b); g(c)
結果:
generic treatment of A
called from g: f A
special treatment of DA
called from g: f DA
special treatment of DA
called from g: f DA //PROBLEM: g forgot that this DA was actually a DDA
(2) 代わりに、テンプレートを使用してみてください。
template<typename T>
void h(T t) {
std::cout << "generic treatment of A" << std::endl;
std::cout << "called from h: ";
f(t);
}
template<>
void h<>(DA t) {
std::cout << "special treatment of DA" << std::endl;
std::cout << "called from h: ";
f(t);
}
その結果:
generic treatment of A
called from h: f A
special treatment of DA
called from h: f DA
generic treatment of A //PROBLEM: template specialization is not used
called from h: f DDA
では、テンプレートの特殊化を使用せず、特殊な場合に非テンプレート関数を定義するのはどうですか? (非常に紛らわしい問題に関する記事。)記事によると「第一級市民」である非テンプレート関数は、それを使用するには型変換が必要であるため、失われるように見えるため、まったく同じように動作することがわかりました。 . そして、それが使用された場合、最初のソリューションに戻るだけで (私は推測します)、DDA のタイプを忘れてしまいます。
(3) 今、私は仕事でこのコードに出くわしました。
template<typename T>
void i(T t, void* magic) {
std::cout << "generic treatment of A" << std::endl;
std::cout << "called from i: ";
f(t);
}
template<typename T>
void i(T t, DA* magic) {
std::cout << "special treatment of DA" << std::endl;
std::cout << "called from i: ";
f(t);
}
しかし、それは私が望むことを正確に行うようです:
generic treatment of A
called from i: f A
special treatment of DA
called from i: f DA
special treatment of DA
called from i: f DDA
奇妙な方法で呼び出す必要がありますが、 i(a, &a); です。i(b, &b); i(c,&c);
今、私はいくつかの質問があります:
- なぜこれが機能するのですか?
- それは良い考えだと思いますか?考えられる落とし穴はどこですか?
- この種の専門化を行う他の方法として、どのような提案がありますか?
- (型変換は、テンプレートの半順序などの狂気にどのように適合しますか...)
これがかなり明確だったことを願っています。:)