如何将指针(或引用)存储到std :: set中的对象

时间:2014-01-31 19:52:25

标签: c++ stl

在C ++ 11 STL中是否有任何适当的方法可以在std::set中存储对象指针,并通过对象的operator <方法对它们进行正确排序?

当然,有可能编写自己的Compare类型并将其作为第二个模板参数传递给set,但我想象STL会提供一个更便捷的方式。

一些谷歌搜索显示std::reference_wrapper,在我看来应该允许这样的代码:

#include <functional>
#include <set>

struct T {
    int val;
    bool operator <(T& other) {
        return (this->val < other.val);
    }
};

int main() {
    std::set<std::reference_wrapper<T>> s;
    T a{5};
    s.insert(a);
}

但事实上,这会导致编译错误:

clang++ -std=c++11 -Wall -Wextra -pedantic test.cpp -o test
In file included from test.cpp:1:
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.8.2/../../../../include/c++/4.8.2/functional:49:
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.8.2/../../../../include/c++/4.8.2/bits/stl_function.h:235:20: error: invalid operands to binary expression ('const std::reference_wrapper<T>'
      and 'const std::reference_wrapper<T>')
      { return __x < __y; }
               ~~~ ^ ~~~

(gcc错误类似,但更长)

3 个答案:

答案 0 :(得分:6)

您需要让您的less-than运算符成为非成员,并为其提供const引用参数:

struct T {
    int val;
};

bool operator <(const T& lhs, const T& rhs) {
    return (lhs.val < rhs.val);
}

这允许在std::reference_wrapper<T>运算符的LHS和RHS上从T<进行隐式转换,而成员版本仅允许在RHS上进行隐式转换。 LHS和二元运算符的RHS之间的对称性是将它们作为非成员实现的经典论据之一。

答案 1 :(得分:2)

调用方法的对象不能被隐式转换,因此您需要将比较作为自由函数来实现,以使用来自reference_wrapper&lt; T&gt;的转换。到T。

答案 2 :(得分:0)

正确的方法是为MyStruct创建专门的std::less

namespace std
{
    template<> struct  less<MyStruct>
    {
        bool operator() (const MyStruct& lhs, const MyStruct& rhs) const
        {
            return lhs.a < rhs.a;
        }
    };

}

请记住,std::set默认使用std::less来比较两个元素。

在标题<set>

中定义
template<

    class Key,
    class Compare = std::less<Key>,
    class Allocator = std::allocator<Key>
> class set;

https://github.com/mysql/mysql-connector-python/blob/b034f25ec8037f5d60015bf2ed4ee278ec12fd17/lib/mysql/connector/connection.py#L286-L288