Comparing std::function<>
Asked Answered
B

2

8

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.

Borderland answered 1/5, 2011 at 7:16 Comment(3)
@James: I disagree. The question doesn't ask why it isn't, it asks if it is. If you want to find that question, you have to already know that it isn't.Realtor
@DeadMG: fair enough, but dup of Comparing std::tr1::function<> objects, thenUrsala
@mmutz: They're close, but I'm still not going to call dupe. The TR1 libs can have a different spec to the C++0x libs.Realtor
S
5

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.

Sabah answered 25/9, 2013 at 9:46 Comment(0)
R
8

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==.

Realtor answered 1/5, 2011 at 7:19 Comment(0)
S
5

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.

Sabah answered 25/9, 2013 at 9:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.