0

I have a class, which among other things stores vectors of a few other objects I have defined. I want to define a test() function which checks to see if all the objects are in a valid state and then call this via assert so that it only runs in debug mode and outputs each error that is found. However, only the first error is outputted.

Consider the following toy example:

class Foo
{
public:
    Foo(int index, int data) : _index(index), _some_data(data) {}

    bool test() const
    {
        bool valid = true;
        if (_some_data == 0)
        {
            std::cout << "Error! Foo " << _index << " has invalid data.\n";
            valid = false;
        }
        return valid;
    }

private:
    int _index;
    int _some_data; // for this example, should be non-zero
};

class MyClass
{
public:
    MyClass(std::vector<Foo> foos) : _foos(foos) {}

    bool test() const
    {
        bool valid = true;
        for (auto &foo : _foos)
        {
            valid = valid && foo.test();
        }
        return valid;
    }

private:
    std::vector<Foo> _foos;
};

int main()
{
    Foo foo1(0, 0);
    Foo foo2(1, 0);
    Foo foo3(2, 0);

    std::vector<Foo> foos({foo1, foo2, foo3}); // all three foos in invalid state

    MyClass my_class(foos);
    assert(my_class.test()); // outputs "Error! Foo 0 has invalid data." But does not show me errors in other two foos
}

Why does this output only the first invalid Foo and not every invalid Foo?

I guess this has something to do with the compiler trying to optimise the code (I'm running GCC). As soon as valid is equal to false it does not bother running the rest of the loop. How do I prevent this?

  • You cannot prevent this, short circuiting is mandated by standard. The loop is run as regular, but for every `valid && foo.test();` in second and later loop iterations compiler determines that `valid` is `false` and thus the whole expression is `false`. The only way to make sure each function call happens would be to store result in temporary variable first: `bool test = foo.test(); valid = valid && test;` – Yksisarvinen Nov 07 '22 at 21:48
  • 1
    Okay thanks. I had a look at the similar question that was linked and it says to use & instead of &&. This now works. – Numerical Disintegration Nov 07 '22 at 21:51

0 Answers0