I have a class that has the task to run functions in an async context and therefore can take a function (or method) as input.
Right now I am keeping two functions with different names to take the functions as input, because I need to differentiate between void return type and other return types. Naming both functions the same does not work for me. What I want is that both have the same name and the caller of the function should not need to think about the return type, he can get it, if he wants and if it is possible:
#include <functional>
template<typename Func, typename ...Args>
auto Foo(Func f, Args&&... args)
{
decltype(f(std::forward<Args>(args)...)) ret;
init();
ret = f(std::forward<Args>(args)...);
clean();
return ret;
}
template<typename Func, typename ...Args>
void FooVoid(Func f, Args&&... args)
{
init();
f(std::forward<Args>(args)...);
clean();
}
int Bar(){return 0;}
void Empty() {}
struct A
{
int Bar(){return 0;}
void Empty(){}
};
int main()
{
auto bar = Foo(Bar);
FooVoid(Empty);
A a;
bar = Foo(std::bind(&A::Bar, a));
FooVoid(std::bind(&A::Empty, a));
return 0;
}
What I want is that both functions can have the same name without creating ambiguousity. Right now there is no other limitation. How could I achieve this? Any other recommendations on the code would also be helpful. I am new to this topic!
Since C++17 you can use if constexpr. In the condtion you check if function f
has return type other than void
, if so, call the function and return its value. Otherwise, auto
as return type will be deduced to be void
- no return in false-statement.
template<typename Func, typename ...Args>
auto Foo(Func f, Args&&... args)
{
if constexpr (!std::is_same_v<void,decltype(f(std::forward<Args>(args)...))> )
{
init();
auto ret = f(std::forward<Args>(args)...);
clean();
return ret;
}
else {
init();
f(std::forward<Args>(args)...);
clean();
}
}