Comparing std::functions for equality?
How can I compare two C++11 std::function
s with operator==
, and return true
if both of said function
s refer to the same function pointer?
operator== for std::function compares a std::function with a null pointer, as far as I can tell the standard does not provide any details as to why.
Although, this boost FAQ entry, Why can't I compare boost::function objects with operator== or operator!=? provides a rationale and as far as I can tell should be applicable to std::function as well. Quoting the FAQ:
Comparison between boost::function objects cannot be implemented "well", and therefore will not be implemented. [...]
it then outlines requested solutions similar to Preet's and goes on to say:
The problem occurs when the type of the function objects stored by both f and g doesn't have an operator==[...]
and explains why this has to has to be dealt with in either the assignment operator or constructor and then goes on to say:
All of these problems translate into failures in the boost::function constructors or assignment operator, even if the user never invokes operator==. We can't do that to users.
Update
Found a standards rationale in Accessing the target of a tr1::function object, which is pretty old but is consistent with the boost FAQ and says:
operator== is unimplementable for tr1::function within the C++ language, because we do not have a reliable way to detect if a given type T is Equality Comparable without user assistance.
You can actually get it to work with .target
:
template<typename T, typename... U>
size_t getAddress(std::function<T(U...)> f) {
typedef T(fnType)(U...);
fnType ** fnPointer = f.template target<fnType*>();
return (size_t) *fnPointer;
}
if (getAddress(f) == getAddress(g)) {...}
(Ref: C++ trying to get function address from a std::function)
You could try comparing a
and b
first by comparing their .target_type()
and if these target type ids are the same, then you can compare their .target()
pointers. You can use a mismatching target type as an early out false.