在将共享指针插入到该对象集时不调用类重载运算符“ <”

时间:2018-07-21 12:17:11

标签: c++ stl

请考虑以下程序:

#include <string>
#include <iostream>
#include <set>
#include <memory>

class Boo
{
public:
    using ShPtr = std::shared_ptr<Boo>;

    bool operator < (const Boo& boo) const
    {
        std::cout << "Hello from operator";
        return true;
    }
};


int main(int, char*[])
{
    std::set<std::shared_ptr<Boo>> _container;

    _container.insert(Boo::ShPtr(new Boo()));

    return 0;
}

根据std :: set:的文档

  

在内部,set容器将其所有元素排序如下   由其比较对象指定的条件。元素是   始终按照此顺序插入其各自的位置。

所以我希望每个插入对象都会调用比较对象。

默认情况下,比较对象是

template<typename _Key, typename _Compare = std::less<_Key>,
       typename _Alloc = std::allocator<_Key> >
class set
{
 ...
}

所以在这种特殊情况下是:

template<typename _Sp>

struct _Sp_less : public binary_function<_Sp, _Sp, bool>
{
  bool
  operator()(const _Sp& __lhs, const _Sp& __rhs) const noexcept
  {
typedef typename _Sp::element_type element_type;
return std::less<element_type*>()(__lhs.get(), __rhs.get());
  }
};

通过比较共享指针指向的对象来完成比较。

我的问题是:为什么在我的程序运算符'<'中没有Boo类的对象?

1 个答案:

答案 0 :(得分:0)

Richard Critten注意到:

@SombreroChicken“请注意,shared_ptr的比较运算符仅比较指针值;所指向的实际对象不进行比较。”来源:en.cppreference.com/w/cpp/memory/shared_ptr/operator_cmp因此它可以编译干净,但仅比较指针值

下面的代码按预期工作:

#include <string>
#include <iostream>
#include <set>
#include <memory>

template<typename _Sp>
struct CompShPtrByObj : std::_Sp_less<_Sp>
{
  bool
  operator()(const _Sp& __lhs, const _Sp& __rhs) const noexcept
  {
    typedef typename _Sp::element_type element_type;
    return std::less<element_type>()(*__lhs, *__rhs);
  }
};

class Boo
{
public:
    using ShPtr = std::shared_ptr<Boo>;

    bool operator < (const Boo& boo) const
    {
        std::cout << "Hello form boo";
        return true;
    }
};


int main(int, char*[])
{
    std::set<std::shared_ptr<Boo>, CompShPtrByObj<std::shared_ptr<Boo>>> _container;

    Boo::ShPtr sharedBoo(new Boo());
    Boo::ShPtr sharedBoo2(new Boo());

    _container.insert(sharedBoo);
    _container.insert(sharedBoo2);

    std::set<std::shared_ptr<Boo>, CompShPtrByObj<std::shared_ptr<Boo>>>::iterator iter = _container.find(sharedBoo);

    return 0;
}

但是这种解决方案清楚吗?那种改变默认值的明显工作方式是否会误导使用该容器的任何人?