Can two functors be compared for equality?

A raw function is eventually a pointer. You can dig it out of std::function with std::function::target and then it's simply a comparison of void*.


Directly using std::function::target<T>() as suggested in the Michael Chourdakis's answer is problematic, since to use it you have to know the actual type stored in std::function:

Return value

A pointer to the stored function if target_type() == typeid(T), otherwise a null pointer.

E.g. by using T = void (A::*)() const you restrict yourself to only using void() const member functions of class FSMAction. At this point std::function starts to be no better than a plain member function pointer.


I suggest writing a wrapper for std::function that implements == / != using type erasure. Here's a minimal implementation:

#include <functional>
#include <iostream>
#include <utility>

template <typename T>
class FancyFunction;

template <typename ReturnType, typename ...ParamTypes>
class FancyFunction<ReturnType(ParamTypes...)>
{
    using func_t = std::function<ReturnType(ParamTypes...)>;
    func_t func;
    bool (*eq)(const func_t &, const func_t &) = 0;

  public:
    FancyFunction(decltype(nullptr) = nullptr) {}

    template <typename T>
    FancyFunction(T &&obj)
    {
        func = std::forward<T>(obj);    
        eq = [](const func_t &a, const func_t &b)
        {
            return *a.template target<T>() ==
                   *b.template target<T>();
        };
    }

    explicit operator bool() const
    {
        return bool(func);
    }

    ReturnType operator()(ParamTypes ... params) const
    {
        return func(std::forward<ParamTypes>(params)...);
    }

    bool operator==(const FancyFunction &other) const
    {
        if (func.target_type() != other.func.target_type())
            return 0;
            
        if (!eq)
            return 1;
        
        return eq(func, other.func);
    }
    
    bool operator!=(const FancyFunction &other) const
    {
        return !operator==(other);
    }
};


struct A
{
    void foo() {}
    void bar() {}
};

int main()
{
    FancyFunction<void(A &)> f1(&A::foo), f2(&A::foo), f3(&A::bar);
    std::cout << (f1 == f2) << '\n';
    std::cout << (f1 == f3) << '\n';
}

Try it live

Tags:

C++

C++11

Functor