4

重複の可能性:
C++ でオーバーロードされたテンプレート関数を選択するときの優先順位

テンプレート化された関数を使用すると、さまざまな型を簡単に操作できます。

template<typename T> void destroy(T* obj) {
    delete obj;
}

しかし、ある時点で、クラス階層でいくつかの特殊化を行いたいと考えています。

class Base { virtual void doSomething(); };
class Derived : public Base {};
void destroy(Base* obj) {
    obj->doSomething();
    delete obj;
}

正確な型を渡すと、目的の特殊化された関数が呼び出されましたが、オーバーロード解決のルールは、に渡すとBase*静的なアップキャストを実行するのではなく、一般的なテンプレート化されたバージョンを好むようです。Derived*void detroy()

確かに、考えられるすべての派生型に対してオーバーロードされたすべての関数を作成できますが、保守性は低くなります。

Visual C++ 2008 を使用していますが、上記の問題を回避する方法はありますか?

4

2 に答える 2

5

All things being equal, overload resolution prefers nontemplate functions to function templates. However, in this case, all things are not equal. To match your overload for Base*, a derived-to-base pointer conversion is necessary; no conversion is necessary to match the function template. Thus, the function template is selected for Derived*.

The "simple," albeit probably error-prone, solution would be to cast your Derived* to a Base* before you call the function.

You could, in theory at least, take an SFINAE approach as Ben suggests, but you would have to explicitly disable the generic function template for any types for which you provide specializations, otherwise you'll end up with overload ambiguities. This is even more unmaintainable and error-prone than the explicit cast approach. (Though, someone here may know of another way to get around the overload ambiguity; I'd certainly be interested to know if there was).

于 2010-03-07T06:20:48.920 に答える