基本クラスと派生クラスへの共有ポインターを受け取るオーバーロードされた関数を作成したいと考えています。参照と生のポインターでは機能するようですが、追加の派生クラスの場合の共有ポインターでは機能しません。サンプル コードを参照してください。
#include <memory>
class Base{};
class Derived : public Base {};
class ExtraDerived : public Derived {};
bool IsBase(Base*){ return true; }
bool IsBase(Derived*){ return false; }
bool IsBase(std::shared_ptr<Base>){ return true; }
bool IsBase(std::shared_ptr<Derived>){ return false; }
int main()
{
auto derived = std::make_shared<Derived>();
auto extra_derived = std::make_shared<ExtraDerived>();
// works
auto raw_result_derived = IsBase(derived.get());
auto raw_result_extra_derived = IsBase(extra_derived.get());
auto shared_result_derived = IsBase(derived);
// doesn't work
auto shared_result_extra_derived = IsBase(extra_derived);
}
Visual Studio 2012 を使用すると、「エラー C2668: 'IsBase' : オーバーロードされた関数へのあいまいな呼び出し」が表示されますが、ここでコードを試しても同じ結果が得られますhttp://ideone.com/6uoa0p。
これは望ましい動作のようには見えません (「生の」ものに対して機能するため)。これはテンプレートの制限ですか、これが機能しない別の理由はありますか、それともバグですか? そして、どうすればそれを最も醜い方法で機能させることができますか?
私が思いつくことができる最高のものは
//ugly workaround
bool IsBase(std::shared_ptr<Base>, Base*){ return true; }
bool IsBase(std::shared_ptr<Derived>, Derived*){ return false; }
template<typename T> bool IsBase(std::shared_ptr<T> input )
{
return IsBase(input, input.get());
}