The aim is to provide a generic functor class which makes references able to bind to r-values. The trick is to trick the compiler into thinking that the r-value is an l-value by using a forwarding references. Here is the code:
#include <type_traits>
template <typename Functor>
struct Function {
Functor func;
template <typename ...Args>
inline auto operator() (Args&&... args) {
//I tried to provide a suitable error message if args were not valid parameters, but I can't get it to work...
//static_assert(std::is_invocable_v<Functor, Args...>);
return func(args...);
}
};
Example use case:
# include <iostream>
# include <vector>
int main () {
// Define function
auto push_back = Function([] (std::vector<int>& vec, int num) {vec.push_back(num); return vec;});
auto x = std::vector{1 , 2 ,3 , 4};
// Works on l-values
push_back(x, 5);
std::cout << x[4] << '\n'; // 5
// Works on r-values
auto y = push_back(std::vector{1 ,2 , 3 , 4 , 5}, 6);
std::cout << y[5] << '\n'; // 6
return 0;
}
And finally, one can do this if you want to use old-style c functions:
template <typename R, typename ...Args>
inline auto CFunc(R (*iFunc) (Args...)) {
return Function<R (*) (Args...)>(iFunc);
}
Is this robust code? Are there edge cases I need to be aware about with which my functor class does not work? Also, how could I provide more suitable error messages, eg when typename Functor
is not a functor, or when args...
are not suitable parameters?