Reputation: 1361
I created simple wrapper to catch, report and rethrow exceptions (see below). It works fine for functions, function pointers and std::function
objects but fails to compile for lambdas and functors due to the check for nullptr
. Is there a way to fix this as simply as possible so that wrapper could be used for any kind of callable? Thanks!
#include <functional>
template<typename Func, typename TRet, typename... Args>
TRet wrapper(Func func, TRet exit_code_on_error, Args... args) {
TRet exit_code = exit_code_on_error;
//if (func) // this condition does not compile for lambdas and functors
{
try {
exit_code = func(std::forward<Args>(args)...);
} catch(...) {
// report and possibly rethrow
//throw;
}
}
return exit_code;
}
int test1(double d) {
return (int)d;
}
int test2(std::function<int (double)> f, double d) {
return f(d);
}
struct TestFunctor {
int operator()(double d) {
return (int)d;
}
};
int main() {
// OK:
wrapper(test1, 1, 2.3);
wrapper(&test1, 1, 2.3);
auto p = test1;
wrapper(p, 1, 2.3);
p = nullptr;
wrapper(p, 1, 2.3);
wrapper(test2, 1, test1, 2.3);
// These lines cause the troubles:
wrapper([](double d){ return (int)d; }, 1, 2.3);
wrapper(TestFunctor(), 1, 2.3);
}
Error:
wrapper.hpp: error C2451: conditional expression of type 'Func' is illegal
with
[
Func=main::<lambda_1>
]
Upvotes: 1
Views: 683
Reputation: 180500
We can fix this by first checking if Func
is a pointer type and then if it is, check if it is null pointer. That would look like
template<typename Func, typename TRet, typename... Args>
TRet wrapper(Func func, TRet exit_code_on_error, Args... args) {
if constexpr(std::is_pointer_v<Func> ||
std::is_member_function_pointer_v<Func> ||
std::is_same_v<Func, std::function<TRet(Args...)>>) {
// this will only be compiled if Func is a pointer type or std::function
if (func == nullptr)
return exit_code_on_error;
}
try {
return func(std::forward<Args>(args)...);
} catch(...) {
// report and rethrow if needed
//throw;
}
return exit_code_on_error;
}
Upvotes: 5