I am in the middle of writing some generic code for a future library. I came across the following problem inside a template function. Consider the code below:
template<class F>
auto foo(F &&f) {
auto result = std::forward<F>(f)(/*some args*/);
//do some generic stuff
return result;
}
It will work fine, unless I pass to it a function that returns void
like:
foo([](){});
Now, of course, I could use some std::enable_if
magic to check the return type and perform specialization for a function returning void
that looks like this:
template<class F, class = /*enable if stuff*/>
void foo(F &&f) {
std::forward<F>(f)(/*some args*/);
//do some generic stuff
}
But that would awfully duplicate code for actually logically equivalent functions. Can this be done easily in a generic way for both void
-returning and non-void
-returning functions in a elegant way?
EDIT:
there is data dependency between function f()
and generic stuff I want to do, so I do not take code like this into account:
template<class F>
auto foo(F &&f) {
//do some generic stuff
return std::forward<F>(f)(/*some args*/);
}
if you can place the "some generic stuff" in the destructor of a bar
class (inside a security try/catch block, if you're not sure that doesn't throw exceptions, as pointed by Drax), you can simply write
template <typename F>
auto foo (F &&f)
{
bar b;
return std::forward<F>(f)(/*some args*/);
}
So the compiler compute f(/*some args*/)
, exec the destructor of b
and return the computed value (or nothing).
Observe that return func();
, where func()
is a function returning void
, is perfectly legal.