1

我必须使用 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() 函数不匹配。

有没有办法做到这一点?

4

3 回答 3

3

非静态成员函数采用隐式的第一个参数 for 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;

};
于 2013-06-22T12:23:04.077 回答
0

您的示例代码中有许多错误。

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

第一个错误:

bool compare_identifier(int Identifier, int Identifier);

您不能为两个函数参数使用相同的标识符(此外,与样式相关的函数参数应该全小写或驼峰式),例如

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;
};
于 2013-06-22T13:03:38.733 回答
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!
} 

关注评论

make compare_identifier() static(in 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成员。

于 2013-06-22T12:48:10.117 回答