Custom arguments to std::set comparison function

本小妞迷上赌 提交于 2021-02-08 12:01:22

问题


I know how to pass a regular comparison class or function to set::set<>.

I am writing some test code and I want to emulate some C libraries using STL's std::set and I want to be able to pass a C callback to the comparison object so a different comparison takes place.

I have the following theoretical code:

struct MyClass
{
    int a;
};

typedef bool (*user_callback_t)(void *, void *);
class MyComparison
{
private:
    user_callback_t cb = nullptr;
public:
    MyComparison(user_callback_t cb): cb(cb) { }
    MyComparison() {}
    bool operator()(const MyClass &a, const MyClass &b) const
    {
        return cb((void *)&a, (void *)&b);
    }
};

int f1()
{
    auto cmp = [](void *a, void *b) -> bool
    {
        return *(int *)a < *(int *)b;
    };

    MyComparison mycmp(cmp);

    std::set<MyClass, MyComparison> m1;

    m1.insert({ 1 });
    m1.insert({ 2 });
    m1.insert({ 3 });

    return 0;
};

Now notice how I can do:

   std::set<MyClass, MyComparison> m1;

But I cannot, somehow, instantiate a MyComparison object, pass it "cmp" and then use that initialize comparison object with that specific set.

Is there a way to achieve that?


回答1:


Your assertion that you can't pass a MyComparison instance to std::set for it to use it is wrong. There is a constructor for std::set expecting just that (in C++11):

explicit set( const Compare& comp = Compare(),
              const Allocator& alloc = Allocator() );

So your MyComparison can be passed as first argument.

std::set<MyClass, MyComparison> m1(mycmp);

If you don't have C++11 or newer available, then this constructor overload is non-existing and you need to use another one:

template< class InputIt >
set( InputIt first, InputIt last,
     const Compare& comp = Compare(),
     const Allocator& alloc = Allocator() );

This one however expects an interator range in the first two arguments. Since we don't actually want to construct from a range, they need to be dummies. You could do someting like:

std::vector<int> dummy;
std::set<MyClass, MyComparison> m1(dummy.begin(), dummy.end(), mycomp);

dummy will not be used afterwards. I am not sure whether there is a nicer solution besides implementing a dummy iterator class.

See http://en.cppreference.com/w/cpp/container/set/set for full reference on constructors of std::set.



来源:https://stackoverflow.com/questions/39884827/custom-arguments-to-stdset-comparison-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!