The main problem is that most functional objects are not comparable. While simple function pointers and custom function objects with the equality operator can be compared, lambdas, the result of std::bind() , etc. Can not. Using the address of function objects to identify them is usually not an appropriate approach, since objects are usually copied. It is possible to use std::reference_wrapper<Fun> to avoid copying them, but the objects stored in std::function<F> will still have a different address.
With C ++ 11 variation templates, itโs easy enough to create a custom version of std::function<...> that provides a means of comparison. There may be two versions:
- One version that accepts arbitrary function objects, but can obviously only compare the compared function objects: depending on whether the constructor argument is used for the equality operator or not a suitable base class.
- One version, which always provides a working comparison and, obviously, cannot be used with objects that do not correspond to equality.
The latter is a little easier to identify and will look something like this:
template <typename...> class comparable_function; template <typename RC, typename... Args> class comparable_function<RC(Args...)> { struct base { virtual ~base() {} virtual RC call(Args... args) = 0; virtual base* clone() const = 0; virtual bool compare(base const*) const = 0; }; template <typename Fun> struct concrete: base { Fun fun; concrete(Fun const& fun): fun(fun) {} RC call(Args... args) { return this->fun(args...); } base* clone() const { return new concrete<Fun>(this->fun); } bool compare(base const* other) const { concrete const* o = dynamic_cast<concrete<Fun>>(other); return o && this->fun == o->fun; } }; std::unique_ptr<base> fun; public: template <typename Fun> comparable_function(Fun fun): fun(new concrete<Fun>(fun)) {} comparable_function(comparable_function const& other): fun(other.fun->clone()) {} RC operator()(Args... args) { return this->fun->call(args); } bool operator== (comparable_function const& other) const { return this->fun->compare(other.fun.get()); } bool operator!= (comparable_function const& other) { return !(this == other); } };
I think I forgot (and / or did not understand) something, but rather what I need. For an optionally comparable version, you have two concrete versions: one that is implemented above, and the other that always returns false . Depending on whether the == operator for Fun exists in the constructor, you must create one or the other.
source share