С++ 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-квалификациями).