Consider this code:
try {
const Asdf &a = map1.at(index1);
const Bsdf &b = map2.at(index2);
} catch(std::out_of_range&) {
return false;
}
// <code>
std::cout<<a[b[42]]; // May throw std::out_of_range which should not be caught here.
return true;
<code>
uses a and b. I have two options:
<code>
in the try blockThe first option is wrong because if <code>
throws std::out_of_range
the function will return false, which should only happen if the map lookup fails.
The second option can be a bit ugly:
const Asdf *a;
const Bsdf *b;
try {
a = &map1.at(index1); // What?
b = &map2.at(index2);
} catch(std::out_of_range&) {
return false;
}
std::cout << (*a)[(*b)[42]];
return true;
Is there a better way? Something like try-except-else in Python would be nice, but that doesn't exist in C++.
Variables in try block So, if you declare a variable in try block, (for that matter in any block) it will be local to that particular block, the life time of the variable expires after the execution of the block. Therefore, you cannot access any variable declared in a block, outside it.
Variables declared within the try/catch block are not in scope in the containing block, for the same reason that all other variable declarations are local to the scope in which they occur: That's how the specification defines it. :-) (More below, including a reply to your comment.)
Variables declared inside a try or catch block are local to the scope of the block.
In simple terms, scope of a variable is its lifetime in the program. This means that the scope of a variable is the block of code in the entire program where the variable is declared, used, and can be modified.
It's not necessary to do any exception handling. std::map::find
, given a key, will give you an iterator. If the element doesn't exist within the map, then find
will return the end
iterator (i.e. map.end()
).
When de-referencing the iterator, you will receive a pair of values. The first being the key and the second being the object.
auto aIt = map1.find(index1);
auto bIt = map2.find(index2);
if(aIt == map1.end() || bIt == map2.end())
{
return false;
}
const Asdf &a = aIt->second;
const Bsdf &b = bIt->second;
std::cout << a[b[42]];
return true;
Note that iterators in C++ are defined such that the begin
iterator is at the start and the end
iterator is past the last element (http://en.cppreference.com/w/cpp/iterator/end), i.e. the range for iterators within a container is: [begin, end).
Why include the code in the try catch, embedding it in its own try catch block to make the difference between the two cases?
try {
const Asdf &a = map1.at(index1);
const Bsdf &b = map2.at(index2);
try {
// <code>
std::cout<<a[b[42]]; // May throw std::out_of_range which should not be caught here.
} catch (std::out_of_range&) {}
} catch(std::out_of_range&) {
return false;
}
return true;
But of course in this approach you can't forward to the outside of your function an out_of_range
that would occur in your <code>
.
The other alternative is to simply check existence of the keys using map::count()
without the need for exception catching:
if (map1.count(index1)==0 || map2.count(index2)==0) {
return false;
}
const Asdf &a = map1.at(index1);
const Bsdf &b = map2.at(index2);
// <code>
std::cout<<a[b[42]];
return true;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With