最初に、他の人がすでに指摘しているように、継承は進むべき道ではないということです。しかし、受け入れられた回答で提案された複雑なラッパーではなく、もっと簡単なことをします。独自の型に独自のコンパレータを実装します。
namespace myns {
struct mytype {
int value;
};
bool operator<( mytype const& lhs, mytype const& rhs ) {
return lhs.value < rhs.value;
}
bool operator<( std::shared_ptr<mytype> const & lhs, std::shared_ptr<mytype> const & rhs )
{
// Handle the possibility that the pointers might be NULL!!!
// ... then ...
return *lhs < *rhs;
}
}
まったく魔法ではない魔法は、Argument Dependent Lookup (別名、Koening Lookup または ADL)です。コンパイラが関数呼び出しに遭遇すると、引数の名前空間をルックアップに追加します。オブジェクトがテンプレートのインスタンス化である場合、コンパイラは、テンプレートのインスタンス化に使用される型の名前空間も追加します。だから:
int main() {
std::shared_ptr<myns::mytype> a, b;
if ( a < b ) { // [1]
std::cout << "less\n";
} else {
std::cout << "more\n";
}
}
[1] では、anda
とb
はオブジェクトのユーザー定義型 (*)であるため、 ADL が開始され、ルックアップ セットにstd
と の両方が追加されます。myns
次に、operator<
forの標準的な定義std::shared_ptr
は次のとおりです。
template<class T, class U>
bool std::operator<(shared_ptr<T> const& a, shared_ptr<U> const& b) noexcept;
また、追加myns
して追加します:
bool myns::operator<( mytype const& lhs, mytype const& rhs );
myns::operator<
次に、ルックアップが終了した後、オーバーロードの解決が開始され、呼び出しよりも適切な一致であると判断さstd::operator<
れます。これは完全な一致であり、その場合は非テンプレートが優先されるためです。operator<
その後、標準の代わりに独自のものを呼び出します。
あなたのタイプが実際にテンプレートである場合、これはもう少し複雑になります。そうである場合は、コメントをドロップしてください。回答を拡張します。
(*)これは少し単純化したものです。operator<
メンバー関数またはフリー関数の両方として実装できるため、コンパイラは内部std::shared_ptr<>
でメンバーoperator<
(標準には存在しない) とその仲間をチェックします。mytype
また、関数の内部も調べfriend
ます...など。しかし、最終的には正しいものを見つけるでしょう。