C ++ STL集的比较函数:比较函数可以是类的成员函数吗?

时间:2013-06-22 12:17:37

标签: c++ stl set

我必须使用STL集,我想定义自己的比较函数。但是根据我的要求,这个比较函数不应该是全局的,而应该是一个类的公共成员。

//CLASS DEFINITION
class IDENTIFERS
{
public:
         IDENTIFIERS();
         ~IDENTIFIERS();
bool     compare_identifier(int Identifier, int Identifier);

public:
std::set <Identifier, bool(*)(Identifier, Identifier)>      set_instance;

};

//CLASS Constructor
IDENTIFIERS::IDENTIFIERS()
{
std::set <Identifier, bool(*)(Identifier, Identifier)>   set_instance(compare_identifier);
}

如果我写一个代码如上所述。它没有编译,因为比较函数的原型与compare_identifier()函数不匹配。

有办法吗?

3 个答案:

答案 0 :(得分:2)

非静态成员函数为this采用隐式第一个参数,因此compare_identifier实际上有三个参数。如果您需要它是非静态成员函数,则需要将成员函数的隐式第一个参数绑定到IDENTIFIERS的实例,例如,

#include <set>
#include <functional>

struct Identifier { int id; };

class IDENTIFERS
{
public:
  IDENTIFERS() : set_instance(std::bind(&IDENTIFERS::compare_identifier,
                                        this,                                               
                                        std::placeholders::_1,
                                        std::placeholders::_2))
  {}
  bool  compare_identifier(const Identifier& lhs, const Identifier& rhs)
  {
    return lhs.id < rhs.id;
  }

public:
  std::set <Identifier, std::function<bool(const Identifier&, const Identifier&)>> set_instance;

};

答案 1 :(得分:0)

制作compare_identifier() static是解决此问题的最简单方法。以下是如何修复代码以便编译,假设Identifier在其他地方定义:

// Watch for the typo (missing 'I') in your code above
class IDENTIFIERS // Note, all-uppercase names are usually reserved for macros
{
public:
    IDENTIFIERS();

    // N.B: This function needs to take two `Identifier`s as its arguments
    // (not two `int`s)    
    static bool compare_identifier(Identifier const &l, Identifier const& r)
    {
       return l.custom_less_than(r);
    }

    // typedefs can make your code more readable, especially with function pointers.
    typedef bool (*identifier_comparator)(Identifier const &l, Identifier const& r);
    typedef std::set<Identifier, identifier_comparator> identifier_set;
    identifier_set set_instance;
};

IDENTIFIERS::IDENTIFIERS()
    :set_instance(compare_identifier) // Initialise here
{
    // Don't shadow `set_instance` in the body of the constructor!
} 

以下评论

制作compare_identifier() static(在IDENTIFIERS中)会影响Identifier class成员的可访问性。比较两个Identifier对象的逻辑应该位于Identifier内,如下所示:

class Identifier
{
public:
    // If you define this, then you won't need to specify a custom comparator
    bool operator <(Identifier const& r) const
    {
        // return true if `*this` is logically less-than `r`; false otherwise.
    }

    bool custom_less_than(Identifier const& r) const
    {
        // Some other way of comparing objects. Perhaps reverse-alphabetically
        // or similar.
        // return true if `*this` is logically less-than `r`; false otherwise.
    } 
};

...或免费功能,但这些人无法访问private成员。

答案 2 :(得分:0)

示例代码中存在许多错误。

第零个错误在某种程度上与样式相关:类应该被命名为全小写 - 带下划线或CamelCase。

第一个错误:

bool compare_identifier(int Identifier, int Identifier);

你不能为两个函数参数设置相同的标识符(同样,与样式相关的函数参数应该是全小写或者是camelCased),比如

bool compare_identifier(int id1, int id2);

第二个错误是:

std::set <Identifier, bool(*)(Identifier, Identifier)> set_instance;

假设您某处有class Identifier。因为你的班级叫IDENTIFIERS,所以有些东西告诉我你没有。如果你有一个Identifier类,我应该假设你的compare_identifier函数是这样的:

bool compare_identifier(const Identifier& id1, const Identifier& id2);

您的set_instance声明就像:

std::set<Identifier, bool(*)(const Identifier&, const Identifier&)> set_instance;

第三个错误是您的构造函数没有按照您的假设执行(构造set_instance成员),但是(如果在语法上有效)构造局部变量set_instance。所以,你的构造函数应该是这样的:

IdentifierBucket::IdentifierBucket() :
  set_instance(std::bind(compare_identifier, this, _1, _2)) {
}

但所有这一切都没有实际意义......因为set的比较器也没有按照你的想法做(看看两个项是否相等)但它给了它们顺序(默认比较器为std::less ...

真正想要的是:

#include <set>
#include <functional>

struct Identifier {};

struct IdentifierComparator {
  IdentifierComparator() {};
  bool operator()(Identifier id1, Identifier id2); // WRITE THIS
};

class IdentifierBucket {
public:
  IdentifierBucket() {};
  ~IdentifierBucket() {};

private:
  std::set <Identifier, IdentifierComparator> set_instance;
};