Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Comparing std::function<>

Tags:

c++

c++11

tr1

Is it possible to somehow compare two std::tr1::function<> objects? What if I have a collection of function<void(int,float)> objects and want to add and remove event handlers? Adding is trivial, but finding the one to be removed seems to be impossible.

like image 727
Marc Andreson Avatar asked May 01 '11 07:05

Marc Andreson


2 Answers

Can't be done, put simply. std::function (in all of it's iterations, including boost::function and std::tr1::function) does not support operator==.

like image 60
Puppy Avatar answered Sep 24 '22 10:09

Puppy


Based on information from Stack Overflow at the following link, it IS possible but only if you wrap the std::function object in its own class.

std::vector of std::function

By using a wrapper class, you can test whether two wrapped std::function pointers are equal, but that doesn't tell you anything about what the std::function wraps. So, changing your design is probably a better approach.

edit: I came back to show the way I've solved a very similar problem.

0) Typedefs for conciseness.

    using std::placeholders;
    typedef std::function < void ( int, float ) > some_func;
    typedef std::pair < intptr_t, intptr_t > method_hash;
  1. Write your collection of std::function objects by binding pointers to methods or functions. Where you are doing this for static functions, omit some_object_ptr.

    some_func some_method ( std::bind ( some_method_ptr, 
                                        some_object_ptr, _1, _2 ) 
    
  2. Use std::reinterpret_cast < intptr_t > to create a unique hash for your function, and use it with std::pair to do so for methods.

     method_hash pairID ( reinterpret_cast < intptr_t > ( some_object_ptr ), 
                          reinterpret_cast < intptr_t > ( some_method_ptr ) );
    
  3. Now your pairID can be stored in a vector or other container/array. Just be sure to maintain that the indices are aligned so that a hash always corresponds to the correct std::function object, and you can then use find ( ) to get an iterator to its position and distance ( ) to convert the iterator to the required index.

Note that this will have to be done every time your container is generated. Since it's based on pointers, the hashes will change over different runs of your program.

like image 24
JPHarford Avatar answered Sep 23 '22 10:09

JPHarford