Comparing std::functions for equality?

2019-01-17 19:38发布

How can I compare two C++11 std::functions with operator==, and return true if both of said functions refer to the same function pointer?

5条回答
放我归山
2楼-- · 2019-01-17 20:12

Be aware that equality of functions (deciding if two functions have always the same observable behavior) is an undecidable problem in lambda calculus (and that is why many programming languages forbid comparing functions).

So even if the == test compiles, it would at most just test that the code is identical (has the same address), not that the compared functions have the same behaviour.

查看更多
乱世女痞
3楼-- · 2019-01-17 20:14

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.

查看更多
疯言疯语
4楼-- · 2019-01-17 20:14

If the std::function<T(U...)> f is a member function,the fnPointer will be null.

查看更多
一夜七次
5楼-- · 2019-01-17 20:18

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.

查看更多
迷人小祖宗
6楼-- · 2019-01-17 20:27

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)

查看更多
登录 后发表回答