You probably know situations like this where you just want to assign to a (const
) variable with an expression which might fail (throw) (e.g.container.at()
) which forces you to write boiler plate code:
void foo(const string &key) {
auto it = data_store.find(key);
if (it == data_store.end()) {
return;
}
const auto & element = it->second;
...
go on with `element`...
...
}
In Python you could write code like this:
def foo(name):
try:
element = data_store[key]
except KeyError:
return
..
go on with `element`
..
.. with is less noisy because you don't introduce that useless extra it
just for checking existence.
If C++'s try
would not introduce a variable scope you could just use at()
:
void foo(const string &key) {
try {
const auto & element = data_store.at(key);
} catch (const out_of_range &) {
return;
}
...
go on with `element`...
...
}
What's the way to go here if you don't want to abandon constness and keep your code clean?
If lambdas only could have a try
/catch
body you could write
void foo(const string &key) {
const auto & element = [&] () -> T try {
return data_store.at(key);
} catch () {
return;
} ();
...
go on with `element`...
...
}
Some answers to similar questions suggest try
/catch
blocks around all the code:
void foo(const string &key) {
try {
const auto & element = data_store.at(key);
...
go on with `element`...
...
} catch (const out_of_range &) {
return;
} catch (some other exception) {
...
} catch (some other exception) {
...
}
}
But I don't like this because of three reasons:
- there's no visual correlation between
at()
and it'scatch
block - there might be code that also need you to handle
out_of_range
- you have to write nested code
Which (nice, short and clean) alternatives do you know?