Consider
#include <tuple>
template <typename... F>
auto execute (F... f) {
return std::make_tuple(f(0)...);
}
int foo(int) { return 5; }
int bar(int) { return 3; }
int main() {
auto tuple = execute(foo, bar);
}
What is a good workaround so that bar can return void?
I tried this, but it won't compile:
#include <tuple>
struct Void { };
template <typename T>
T check(T n) { return n; }
Void check(void) { return Void{}; }
template <typename... F>
auto execute (F... f) {
return std::make_tuple(check(f(0))...);
}
int foo(int) { return 5; }
void bar(int) { }
int main() {
auto tuple = execute(foo, bar);
}
Update: I have a tentative solution, but it only works if we know that the arguments passed is always int 0. I'll try to make it work in any general setting. Or perhaps use std::optional like Steve suggested.
#include <tuple>
#include <type_traits>
struct Void { };
template <typename F>
auto execute_h (F f, std::enable_if_t<!std::is_void_v<std::result_of_t<F(int)>>>* = nullptr) {
const auto result = f(0);
return result;
}
template <typename F>
auto execute_h (F f, std::enable_if_t<std::is_void_v<std::result_of_t<F(int)>>>* = nullptr) {
f(0);
return Void{};
}
template <typename... F>
auto execute (F... f) {
return std::make_tuple(execute_h(f)...);
}
int foo(int) { return 5; }
void bar(int) { }
int main() {
auto tuple = execute(foo, bar);
}