С++ 0x Сравнение смарт-указателей: непоследовательно, какое обоснование?

В С++ 0x (n3126) интеллектуальные указатели можно сравнивать как с точки зрения равенства, так и для равенства. Однако, как это делается, мне кажется непоследовательным.

Например, shared_ptr определяет operator< эквивалентно:

template <typename T, typename U>
bool operator<(const shared_ptr<T>& a, const shared_ptr<T>& b)
{
    return std::less<void*>()(a.get(), b.get());
}

Использование std::less обеспечивает полное упорядочение относительно значений указателя, в отличие от сравнения реляционных указателей ванили, которое не указано.

Однако unique_ptr определяет тот же оператор, что и:

template <typename T1, typename D1, typename T2, typename D2>
bool operator<(const unique_ptr<T1, D1>& a, const unique_ptr<T2, D2>& b)
{
    return a.get() < b.get();
}

Он также определял другие реляционные операторы аналогичным образом.


Почему изменение метода и "полноты"? То есть, почему shared_ptr использует std::less, а unique_ptr использует встроенный operator<? И почему не shared_ptr также предоставляют другие реляционные операторы, такие как unique_ptr?

Я могу понять логику выбора:

  • по отношению к методу: он представляет собой указатель, поэтому просто используйте встроенные операторы указателя, так как он должен использоваться в ассоциативном контейнере, чтобы обеспечить полное упорядочение (например, указатель ванили с предикатом std::less по умолчанию аргумент шаблона)
  • в отношении полноты: он представляет указатель, поэтому предоставляет все те же сопоставления, что и указатель, по сравнению с типом класса и должен быть менее сопоставимым для использования в ассоциативном контейнере, поэтому только это требование

Но я не понимаю, почему выбор изменяется в зависимости от типа интеллектуального указателя. Что мне не хватает?


Бонус/связанный: std::shared_ptr, по-видимому, следовал из boost::shared_ptr, а последний опускает другие реляционные операторы "по дизайну" (и поэтому std::shared_ptr тоже). Почему это?

Ответ 1

Это был дефект в проектах С++ 11; был обнаружен отчет о дефекте, чтобы изменить перегруженные операционные операции std::unique_ptr для использования std::less: см. LWG Defect 1297.

Это было исправлено вовремя для окончательной спецификации С++ 11. С++ 11 §20.7.1.4 [unique.ptr.special]/5 указывает, что перегрузка operator<:

Возвращает: less<CT>()(x.get(), y.get())

где x и y - два операнда оператора, а CT - общий тип двух указателей (поскольку можно сопоставить указатели на разные типы, например, с разными cv-квалификациями).