The C++11 driver throws exceptions to indicate errors that the user must handle. Exceptions require the programmer to deal with them - return values may be ignored.
Note that in C++11 (or particularly C++14) you can easily transmute a throwing function into one that returns values, if you are so inclined:
const auto make_nothrow = [](auto callable) {
return [callable(std::move(callable))](auto ...args) noexcept {
try {
return std::make_tuple(
std::experimental::make_optional(
callable(args...)
),
std::exception_ptr()
);
}
catch(...) {
return std::make_tuple(
std::experimental::optional<decltype(callable(args...))>(),
std::current_exception()
);
}
};
};
double throws(int x, double y) {
if (x != y)
throw std::runtime_error("I'm an exception");
return x + y;
}
int main(int argc, char* argv[]) {
auto doesnt_throw = make_nothrow(throws);
auto result1 = doesnt_throw(argc, 1.0);
std::cout << *std::get<0>(result1) << std::endl;
auto result2 = doesnt_throw(argc, 2.0);
return EXIT_SUCCESS;
}
I've used C++14 to reduce the template verbiage here, and std::optional and std::tuple here to simulate a variant type, but if you have a proper variant like boost::variant, you can do even better.
Thanks,
Andrew