Бен Фойгт на правильном пути - за исключением, конечно, у нас нет концепций.
template<
typename Lhs
, typename Rhs
, typename = typename std::enable_if<
/* magic */
>::type
>
bool
operator==(Lhs const& lhs, Rhs const& rhs)
{
return lhs.get() == rhs.get();
}
Это должно быть в одном и том же пространстве имен a_ptr
и b_ptr
для того, чтобы ADL пнул (поэтому, если они находятся в отдельных пространствах имен, вам нужна одна версия каждого оператора для каждого пространства имен).
Есть несколько возможностей для работы волшебной черты. Концептуально самым простым является наличие признака, специализированного для каждого типа указателя, который вас интересует:
template<typename T>
struct is_smart_pointer: std::false_type {};
template<typename T, typename D>
struct is_smart_pointer<std::unique_ptr<T, D>>: std::true_type {};
// and so on...
Более сложная черта будет проверять, поддерживает ли тип член get
. На самом деле нам не нужна эта черта!
template<typename Lhs, typename Rhs>
auto operator==(Lhs const& lhs, Rhs const& rhs)
-> decltype( lhs.get() == rhs.get() )
{
return lhs.get() == rhs.get();
}
Этот простой оператор будет выбран ADL, за исключением того, что он сам выдаст SFINAE, если один из типов не поддерживает get
, или если сравнение не работает.