I have some function that can take some arguments and callable object(last argument) as callback with results. I want to transform it to a regular call. I tried this approach and it works, but I must specify arguments types every time.
Is there a solution that can help me with automatically deducing callback arguments types and transform them into return type from function?
#include <functional>
#include <iostream>
void foo1(std::function<void(int)> &&f) {
f(42);
}
void foo1(std::string arg, std::function<void(std::string)> &&f) {
f(std::move(arg));
}
void foo2(std::function<void(float)> &&f) {
f(42.42f);
}
template <typename F>
void foo3(F &&f) {
f(42);
}
template <typename Arg>
auto call(auto &&f) {
Arg res;
f([&res](Arg arg) {
res = std::move(arg);
});
return res;
}
int main() {
std::cout << call<float>([](auto &&callback) { foo2(callback); }) << std::endl;
std::cout << call<int>([](auto &&callback) { foo1(callback); }) << std::endl;
std::cout << call<std::string>([](auto &&callback) { foo1("hello", callback); }) << std::endl;
// should work not only with std::function
std::cout << call<int>([](auto &&callback) { foo3(callback); }) << std::endl;
// is there a way to automatically deduce return type from callback?
// std::cout << call<auto>([](auto &&callback) { foo2(callback); }) << std::endl;
// std::cout << call<auto>([](auto &&callback) { foo3(callback); }) << std::endl;
// // this shouldn't compile, cause of ambiguous call
// std::cout << call<auto>([](auto &&callback) { foo1(callback); }) << std::endl;
}
If possible, I also want to return tuple with results if callback has multiple arguments
void foo4(std::function<void(float, int)> &&f) {
f(42.42f, 42);
}
auto [a, b] = call<auto>([](auto &&callback) { foo4(callback); });
I'll be appreciated for any help with this.