One way is to move use(var)
into the try block, but this introduces a whole load of nesting
You could move use(var)
out to a separate function and call that in your try
block:
void use(var_type var) {
//...
}
for(const auto& arg : args) {
try {
use(create(arg));
} catch(const std::invalid_argument& e) {
continue;
}
}
Since you have no control over create
or the use
block and want to make sure that you don't catch anything thrown in the use
block, you can catch and rethrow the create
exception as a different type to be able to catch that only. Since exceptions should only happen in exceptional cases, this overhead should not be any problem.
Example:
struct create_error : std::invalid_argument {
using std::invalid_argument::invalid_argument;
explicit create_error(const std::invalid_argument& e) : std::invalid_argument(e) {}
};
auto create_wrapper(const arg_type& arg) {
try {
return create(arg);
}
catch(const std::invalid_argument& ex) {
throw create_error(ex);
}
}
void use(var_type var) {
// may throw std::invalid_argument, but it won't be caught below
}
for(const auto& arg : args) {
try {
use(create_wrapper(arg));
}
catch(const create_error& e) {
continue;
}
}