问题 C ++ 0x智能指针比较:不一致,理由是什么?


在C ++ 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 提供了关于指针值的总排序,与未指定的vanilla关系指针比较不同。

然而, 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

我可以理解这两种选择背后的理由:

  • 关于方法:它代表一个指针,所以只需使用内置的指针运算符,而不是它需要在一个关联容器中使用,所以提供总排序(就像一个vanilla指针将获得默认值 std::less 谓词模板参数)
  • 关于完整性:它代表一个指针,因此提供与指针相同的所有比较,而它是一个类类型,只需要比在关联容器中使用的相当,所以只提供该要求

但我不明白为什么选择 变化 取决于智能指针类型。我错过了什么?


奖金/相关: std::shared_ptr 似乎已经跟着 boost::shared_ptr,后者省略了“按设计”的其他关系运算符(等等) std::shared_ptr 也是。为什么是这样?


8798
2017-10-14 02:11


起源



答案:


这是C ++ 11草案中的一个缺陷;一个缺陷报告被打开以改变 std::unique_ptr 关系运算符重载使用 std::less:看 LWG缺陷1297

这是最终C ++ 11规范的及时修复。 C ++11§20.7.1.4[unique.ptr.special] / 5指定了 operator< 超载:

返回:  less<CT>()(x.get(), y.get())

哪里 x 和 y 是运算符和运算符的两个操作数 CT 是两个指针的常见类型(因为可以比较指向不同类型的指针,例如具有不同的cv资格)。


12
2017-10-14 02:17



啊,我应该先看看那里。 :)这肯定回答了方法的变化,但你知道为什么 shared_ptr 不会提供所有其他关系运营商? - GManNickG
@GMan:我认为这可能是个错误。它们列在20.9中 <memory> 概要,但它们实际上并不存在于20.9.11.2.7中...... - James McNellis
@James:哦,好的电话。我的目标就是 shared_ptr 部分。嗯,这解决了我的猜测。 (他们应该真的清理它。)谢谢。 - GManNickG
更奇怪的是:即使其他三个关系运算符没有超载 shared_ptr, greater, greater_equal,和 less_equal 类模板都是专门用于的 shared_ptr。 - James McNellis
@GMan:Boost基本原理似乎是这样的:因为你不能使用四个关系运算符来比较C ++中的任意指针,除非那些指针指向某个数组或类的子对象,并且因为你永远不会有shared_ptrs指向对于子对象(至少不在shared_ptr的预期用途中),它们不实现shared_ptr的关系运算符。但是,他们希望您能够使用shared_ptr作为映射键,并且出于某种原因,他们发现重载op <比专门化std :: less更容易(出于兼容性原因,可能)。 - James McNellis


答案:


这是C ++ 11草案中的一个缺陷;一个缺陷报告被打开以改变 std::unique_ptr 关系运算符重载使用 std::less:看 LWG缺陷1297

这是最终C ++ 11规范的及时修复。 C ++11§20.7.1.4[unique.ptr.special] / 5指定了 operator< 超载:

返回:  less<CT>()(x.get(), y.get())

哪里 x 和 y 是运算符和运算符的两个操作数 CT 是两个指针的常见类型(因为可以比较指向不同类型的指针,例如具有不同的cv资格)。


12
2017-10-14 02:17



啊,我应该先看看那里。 :)这肯定回答了方法的变化,但你知道为什么 shared_ptr 不会提供所有其他关系运营商? - GManNickG
@GMan:我认为这可能是个错误。它们列在20.9中 <memory> 概要,但它们实际上并不存在于20.9.11.2.7中...... - James McNellis
@James:哦,好的电话。我的目标就是 shared_ptr 部分。嗯,这解决了我的猜测。 (他们应该真的清理它。)谢谢。 - GManNickG
更奇怪的是:即使其他三个关系运算符没有超载 shared_ptr, greater, greater_equal,和 less_equal 类模板都是专门用于的 shared_ptr。 - James McNellis
@GMan:Boost基本原理似乎是这样的:因为你不能使用四个关系运算符来比较C ++中的任意指针,除非那些指针指向某个数组或类的子对象,并且因为你永远不会有shared_ptrs指向对于子对象(至少不在shared_ptr的预期用途中),它们不实现shared_ptr的关系运算符。但是,他们希望您能够使用shared_ptr作为映射键,并且出于某种原因,他们发现重载op <比专门化std :: less更容易(出于兼容性原因,可能)。 - James McNellis