微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何提供 std::set 与另一个函数的比较函数

如何解决如何提供 std::set 与另一个函数的比较函数

我正在使用一组指向一个类的指针,并提供了一个比较函数来通过比较对象而不是指针来对集合进行排序。我现在正在尝试编写另一个函数并为其提供与集合中使用的相同的比较函数,如下所示:

/* compset.cpp  -  a program to test compare function of std::set  */
#include <cstdio>
#include <cstdlib>
#include <set>

class foo {
    int n;

public:
    foo(int nn)
        : n(nn)
    {
    }
    friend bool operator<(const foo& a,const foo& b);
};

bool operator<(const foo& a,const foo& b)
{
    return (a.n < b.n);
}

struct fooislt {
    bool operator()(foo* a,foo* b) { return (*a < *b); }
};

class bar {
    int m;

public:
    bar(int mm)
        : m(mm)
    {
    }
    void func(std::set<foo*,fooislt>::iterator ita,std::set<foo*,fooislt>::iterator itb,bool (*comp)(foo*,foo*));
};

void bar::func(std::set<foo*,foo*))
{
    if (comp(*ita,*itb)) {
        // Do something
    }
}

int main(int argc,char* argv[])
{
    bar bar1(17);
    std::set<foo*,fooislt> myset;
    // set up myset
    std::set<foo *,fooislt>::iterator it1,it2;
    // determine it1 and it2
    bar1.func(it1,it2,myset.key_comp);
}

来自 g++ 的错误信息是:

compset.cpp:在函数‘int main(int,char**)’中: compset.cpp:40:27: 错误:非静态成员函数'std::set<_key>_Compare,_Alloc>::key_compare std::set<_key _compare _alloc>::key_comp() 的无效使用const [with >_Key = foo*; _Compare = fooislt; _Alloc = std::allocator​​; std::set<_key _compare>_Alloc>::key_compare = fooislt]' 40 | bar1.func(it1,myset.key_comp); | ~~~~~~~~~~ 在 /usr/include/c++/10/set:61 包含的文件中, 来自 compset.cpp:5: /usr/include/c++/10/bits/stl_set.h:327:7: 注意:此处声明 第327话key_comp() 常量 | ^~~~~~~~

我怎样才能做到这一点?

解决方法

有什么问题。

问题在于压缩函数比函数的原始指针更复杂。

定义如下:std::set<foo*,fooislt> 压缩器是一个类型为 fooislt 的类,它定义了 operator()。现在,由于这是一个对象,因此无法将其转换为指向函数的指针。

简单的解决方案是使用 bar::func 的模板,这样压缩函数就会采用正确的类型: https://godbolt.org/z/3Whn89

class bar {
    int m;

public:
    bar(int mm)
        : m(mm)
    {
    }

    template <typename F>
    void func(std::set<foo*,fooislt>::iterator ita,std::set<foo*,fooislt>::iterator itb,F comp);
};

template <typename F>
void bar::func(std::set<foo*,F comp)
{
    if (comp(*ita,*itb)) {
        // Do something
    }
}

或者,您可以使用 std::function<> 隐藏模板使用能够执行正确的转换。 https://godbolt.org/z/frcjdK

class bar {
    int m;

public:
    bar(int mm)
        : m(mm)
    {
    }

    void func(std::set<foo*,std::function<bool(foo*,foo*)> comp);
};

void bar::func(std::set<foo*,foo*)> comp)
{
    if (comp(*ita,*itb)) {
        // Do something
    }
}
,

我发现,感谢 ani1998ket 的评论和 Marek R 对模板的建议,我认为是解决我的问题的最佳方法:使用模板来定义比较函数,并使用 std::set ::key_compare 作为 bar::func 定义中的类型如下:

/* compset.cpp  -  a program to test compare function of std::set  */

#include <stdio.h>
#include <stdlib.h>
#include <set>
template<typename T>
struct isltptr {
  bool operator()(T *t1,T *t2) { return(*t1<*t2); }
};
class foo {
  int n;
public:
  foo(int nn) : n(nn) {}
  bool operator<(const foo &a) { return(n<a.n); }
};
class bar {
  int m;
public:
  bar(int mm) : m(mm) {}
  void func(std::set<foo *,isltptr<foo> >::iterator ita,std::set<foo *,isltptr<foo> >::iterator itb,isltptr<foo> >::key_compare comp);
};
void bar::func(std::set<foo *,isltptr<foo> >::key_compare comp)
{
  if (comp(*ita,*itb)) {
    // Do something
  }
}
int main(int argc,char *argv[])
{
  bar bar1(17);
  std::set<foo *,isltptr<foo> > myset;
  // set up myset
  std::set<foo *,isltptr<foo> >::iterator it1,it2;
  // determine it1 and it2
  bar1.func(it1,it2,myset.key_comp());
}

我发现模板很有用,因为我还有其他需要相同功能的指针集。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。