1

In my project, I have a lot of situations like this:

constexpr size_t element_count = 42;
std::array<bool, element_count> elements;

for(size_t i = 0; i < element_count; ++i){
    if(i > 0 && elements[i - 1]){/*do something*/}
    else{/*do something else*/}
    if(i < element_count - 1 && elements[i + 1]){/*do something*/}
    else{/*do something else*/}
}

Without checking if i > 0 or i < element_count, I'll get undefined behavior. If I use std::array::at instead of operator[], I can get std::out_of_range exceptions instead. I was wondering if there were any problems with just relying on the exception like this:

for(size_t i = 0; i < element_count; ++i){
    try{
        if(elements.at(i - 1)){/*do something*/}
    }
    catch(const std::out_of_range& e){/*do something else*/}
    try{
        if(elements.at(i + 1)){/*do something*/}
    }
    catch(const std::out_of_range& e){/*do something else*/}
}

In this example it's more code, but in my real project it would reduce the amount of code because I'm using lots of multidimensional arrays and doing bounds checking for multiple dimensions.

Willy Goat
  • 1,009
  • 1
  • 9
  • 21
  • 1
    If relevant, you may increase size of your array to avoid bound checking, (and so only `[1; element_count + 1[` are real values). – Jarod42 Jul 21 '17 at 07:39
  • 1
    Note that you 2 snippets doesn't do the same things (when value is in range and false). – Jarod42 Jul 21 '17 at 07:41

1 Answers1

0

There isn't a problem in the sense that it will work, but that's about it. Using exceptions for basic flow control (which is what you seem to be doing here) is usually frowned upon, with reason, and I don't think I've ever seen it like this in a loop:

  • makes reading and reasoning about code harder, also because it's unexpected one uses exceptions for flow control (instead of for error handling, which is what it is meant for in C++)
  • harder to read usually also means harder to write, and makes it harder to spot mistakes
  • you actually made a mistake already, or at least introduced a behaviour change: i > 0 && elements[i - 1] evaluating to false does not result in 'something else' being called anymore
  • reduction of the amount of code isn't a good goal anymore if it results in less readable or worse code
  • might be less performant

Now it would be interesting to see the actual code, but I suspect it could probably do without any bounds checking whatsoever, e.g. by making the loop start at 1 instead of 0 . Or, if this is a recurrnig pattern, you'd write a helper function (or use an existing on) for iteration with access to multiple elements in one iteration. That would be a reduction in code amount which is actually worth it.

stijn
  • 31,563
  • 13
  • 95
  • 145