I have a wrapper function in C++ 11, designed to be used with lambdas, like so:
template<typename Func>
int WrapExceptions(Func&& f)
{
try
{
return f();
}
catch(std::exception)
{
return -1;
}
}
And I can call it like so:
int rc = WrapExceptions([&]{
DoSomething();
return 0;
});
assert(rc == 0);
And life is OK. What I want to do, though, is overload or specialize the wrapper function such that when the inner function returns void, the outer function returns a default value of 0, e.g.:
int rc = WrapExceptions([&]{
DoSomething();
});
assert(rc == 0);
Can I actually do this in C++ 11? I cannot for the life of me think of how.
You may use SFINAE:
with std::result_of
template<typename Func>
typename std::enable_if<
std::is_convertible<typename std::result_of<Func()>::type, int>::value,
int
>::type
WrapExceptions(Func&& f)
{
try { return f(); }
catch(std::exception) { return -1; }
}
template<typename Func>
typename std::enable_if<
std::is_same<void, typename std::result_of<Func()>::type>::value,
int
>::type
WrapExceptions(Func&& f)
{
try { f(); return 0; /* default value */ }
catch(std::exception) { return -1; }
}
with decltype
:
template<typename Func>
auto
WrapExceptions(Func&& f)
-> typename std::enable_if<
std::is_convertible<decltype(f()), int>::value,
int
>::type
{
try { return f(); }
catch(std::exception) { return -1; }
}
template<typename Func>
auto
WrapExceptions(Func&& f)
-> typename std::enable_if<
std::is_same<void, decltype(f())>::value,
int
>::type
{
try { f(); return 0; }
catch(std::exception) { return -1; }
}