简体   繁体   English

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

[英]Comparison function for C++ STL set: Can comparison function be a member function of a class?

I have to use STL set and I want to define my own comparison function. 我必须使用STL集,我想定义自己的比较函数。 But as per my requirement this comparison function shouldn't be a global, rather should be a public member of a class. 但根据我的要求,这个比较函数不应该是全局的,而应该是一个类的公共成员。

//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);
}

If I write a piece a code as mentioned above. 如果我写一个如上所述的代码。 It doesn't compile as comparison function's prototype doesn't match with compare_identifier() function. 它不会编译,因为比较函数的原型与compare_identifier()函数不匹配。

Is there a way to do it? 有办法吗?

A non-static member function takes an implicit first parameter for this , so your compare_identifier actually has three parameters. 非静态成员函数this采用隐式的第一个参数,因此您的compare_identifier实际上有三个参数。 If you need it to be a non-static member function, you need to bind the member function's implicit first parameter to an instance of IDENTIFIERS , for example, 如果需要它是非静态成员函数,则需要将成员函数的隐式第一个参数绑定到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;

};

Making compare_identifier() static is the easiest way to solve this. 使compare_identifier() static是解决此问题的最简单方法。 Here is how you can fix your code so that it compiles, assuming Identifier is defined elsewhere: 假设在其他地方定义了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!
} 

Following comment 以下评论

Making compare_identifier() static (in IDENTIFIERS ) will not affect the accessibility of members of the Identifier class . 使compare_identifier() static (在IDENTIFIERS不会影响Identifier class成员的可访问性。 The logic to compare two Identifier objects should reside either within Identifier , like this: 比较两个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.
    } 
};

...or within free functions but these won't have access to the private members. ......或在免费功能中,但这些功能无法访问private会员。

There are a number of errors in your sample code. 您的示例代码中存在许多错误。

The zero-th error is somewhat style-related: classes should be named all-lowercase-with-underscores or CamelCase. 第零个错误在某种程度上与样式有关:类应命名为全小写 - 带下划线或CamelCase。

The first error: 第一个错误:

bool compare_identifier(int Identifier, int Identifier);

you can't have the same identifier for both function parameters (also, style-related, function parameters should be all-lowercase or camelCased), like 两个函数参数都不能有相同的标识符(同样,与样式相关,函数参数应该是全小写或者是camelCased),比如

bool compare_identifier(int id1, int id2);

The second error is that this: 第二个错误是:

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

assumes that you have a class Identifier somewhere. 假设您在某处拥有class Identifier Which something tells me you don't, since your class is called IDENTIFIERS . 哪些东西告诉我你没有,因为你的班级被称为IDENTIFIERS If you do have an Identifier class, I should assume that your compare_identifier function is like: 如果有一个Identifier类,我认为你的compare_identifier功能是这样的:

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

and that your set_instance declaration is like: 并且你的set_instance声明如下:

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

The third error is that your constructor does not do what you are assuming it does (constructing the set_instance member), but it would be (if syntatically valid) constructing a local variable called set_instance . 第三个错误是您的构造函数没有按照您的假设执行(构造set_instance成员),但它将(如果在语法上有效)构造一个名为set_instance局部变量 So, your constructor should go something like: 所以,你的构造函数应该是这样的:

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

But all this is moot... because the comparator for set also does not do what you think it does (see if two items are equal or not) but it gives them order (the default comparator is std::less ... 但所有这一切都没有实际意义......因为set的比较器也没有做你认为它做的事情(看两个项是否相等)但是它给了它们顺序 (默认的比较器是std::less ......

What you really want is something like: 真正想要的是:

#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;
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM