为什么没有 bool std::operator==(T1* a, std::shared_ptr b) 的重载<T2>?

Why is there no overload of bool std::operator==(T1* a, std::shared_ptr<T2> b)?

本文关键字:std 重载 ptr gt lt T2 operator bool T1 shared 为什么      更新时间:2023-10-16

我注意到标准库没有为shared_ptr和原始指针的相等操作符提供重载。如果您有一个std::unordered_set<std::shared_ptr<Foo>>,并且希望通过传递原始的Foo*

来擦除元素,这尤其不方便。

没有这样的过载有什么具体的原因吗?在我看来,这很容易实现:

template<typename T1, typename T2>
bool operator==(const T1 * a, const std::shared_ptr<T2> & b) {
    return a == b.get();
}

…这个实现会有什么危险或意想不到的地方吗?

对于unordered_set,您需要的不仅仅是==,还需要hash才能工作。

对于set,透明比较器允许您根据非键类型的内容查找内容。默认情况下,set不是透明的,所以这个操作符不起作用。

一旦您添加了自己的比较器,您就可以覆盖==

遗憾的是,unordered_set目前没有透明选项。为了在unordered_set中查找/擦除/等内容,必须具有密钥类型。

你的超载是有问题的。更好的方法是:

template<class U, class...Ts>
auto operator==( U const* lhs, std::shared_ptr<Ts...> const& rhs )->decltype( lhs == rhs.get() ) {
  return lhs == rhs.get();
}
template<class U, class...Ts>
auto operator==( std::shared_ptr<Ts...> const& lhs, U const* rhs )->decltype( lhs.get() == rhs ) {
  return lhs.get() == rhs;
}

,但请注意,合理地编写上述代码需要c++ 11支持。缺少上述解决方案的最终结果要么是(使用SFINAE)编写混乱,要么声称在没有的类型之间存在==(并且对于其他SFINAE代码实现它来说已经太晚了)。

但是<呢?好吧,原始指针上的<只在同一个对象中是一个好主意,所以在共享指针和原始指针之间公开它似乎是一个可怕的想法。所以现在我们正在接近std::less,并希望在智能指针和非智能指针之间增加透明支持。

我们是否也支持混合智能指针(sharedunique ?)——天真地,你可能会说不,但是如果你替换了删除器,unique_ptr并不一定要表示内存所有权!(shared_ptr也是如此)。具有不同删除器的智能指针应该被认为是相等的还是等价的?根据删除器的不同,数据的含义可能会有很大的不同。

现在,考虑到我已经设法从几分钟的工作中提出了棘手的问题,这样的过载会鼓励原始指针和shared_ptr混合使用,甚至不能帮助解决您想要解决的问题,也许这不是一个好主意。

也许是。这就是为什么它不符合标准的真正原因。

没有人提出,也没有人接受。

如果你认为这是一个好主意,我鼓励你看看提案的过程。检查其他的提案,找出正确的步骤,然后把提案放在一起。

如果这看起来太吓人,您可能想要创建一个提供上述比较操作符的健壮库,并将其添加到boost中,也许人们会使用它并说"哇,我们一直需要它!"

如果您正在使用shared_ptr,传递原始指针是非常危险的,因为如果您有保存原始指针的东西,根据定义,它会破坏引用计数的shared_ptr概念。没有重载的原因可能是为了阻止这种情况。