In mathematics-related context, I'd like to define functors working on <cmath>
functions. For the purpose of this question, we will be using std::invoke
as our functor.
This is ill-formed (live demo):
std::invoke(std::sin, 0.0);
(g++-8.1) error: no matching function for call to 'invoke(<unresolved overloaded function type>, double)'
Indeed, std::sin
is an overload set and the compiler lacks the type information to choose one of those functions.
How could I name a specific function from an overload set? With what could we replace LEFT
and RIGHT
so that the following is well-formed and does what is expected (say, select double std::sin(double)
)?
#include <functional>
#include <cmath>
int main()
{
(void) std::invoke(LEFT std::sin RIGHT, 0.0);
}
If this is not possible, is there a way to define a functor so it is overload-set-aware?
A C++ functor (function object) is a class or struct object that can be called like a function. It overloads the function-call operator () and allows us to use an object like a function.
A function pointer allows a pointer to a function to be passed as a parameter to another function. Function Objects (Functors) - C++ allows the function call operator() to be overloaded, such that an object instantiated from a class can be "called" like a function.
A function assigns to every element of a set X an element of a set Y. A functor assigns to every object of a category C an object of a category D and also assigns to every morphism in C a morphism in D in a way compatible with sources, targets, and composition.
Like others have mentioned, a functor is an object that acts like a function, i.e. it overloads the function call operator.
The easiest way I know to do this is to use a lambda to enable overload lookup
std::invoke([](auto val){return std::sin(val);}, 0.0);
Will allow you to pass any value to invoke
and then the lambda body will handle the actual call and overload resolution will come in then.
You can use a macro to abstract the lambda body out of the call to invoke
using something like
#define FUNCTORIZE(func) [](auto&&... val) noexcept(noexcept(func(std::forward<decltype(val)>(val)...))) -> decltype(auto) {return func(std::forward<decltype(val)>(val)...);}
//...
std::invoke(FUNCTORIZE(std::sin), 0.0);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With