I want to make a method convert that takes a general function bar (can be an std::function, lambda, functor,...) and converts it to an std::function<double(std::array<double, 3>)>. The function bar can either be:
std::array<double, 3> as an argument and returning a double. In this case, convert is not difficult to write:code:
template<typename F>
std::function<double(std::array<double, 3>)> convert (F& bar)
{
std::function<double(std::array<double,3>)> bar_converted = bar;
return bar_converted;
}
doubles as an argument and returning a double. Also in this case, convert is not too difficult to write:code:
template<typename F>
std::function<double(std::array<double, 3>)> convert(F& bar)
{
std::function<double(std::array<double,3>)> bar_converted;
auto array_bar = [bar]( std::array<double, 3> x)->double{ return bar(x[0], x[1], x[2]); };
bar_converted = array_bar;
return bar_converted;
}
The problem is that I do not have a clue how to combine these two convert methods, or whether this is even possible?
I'll start with how I would write this in C++17:
template<typename F>
std::function<double(std::array<double, 3>)> convert(F&& f) // <== NB: forwarding ref
{
if constexpr (std::is_invocable_v<F&, std::array<double, 3>) {
// direct case
return std::forward<F>(f);
} else {
// unpacking case
return [f=std::forward<F>(f)](std::array<double, 3> arr) {
return std::apply(f, arr);
};
}
}
In C++14, you don't have if constexpr, is_invocable, or apply. The first can be achieved by just doing tag dispatch (you invoke a helper function with either std::true_type or std::false_type) and the other two can be implemented in C++14 just fine, and are really useful helper functions that you will likely need for lots of other things anyway.
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