JoligeJ
JoligeJ

Reputation: 67

Why don't these two code snippets behave equivalently?

I have the following function (much simplified for the case of an example):

bool _move (class Square * const cpOldSquare, class Square * const cpNewSquare, const bool & rcOverride = false) {
    if (rcOverride ? true :
        (!!cpOldSquare->mupChesspiece
            && cpOldSquare->mupChesspiece->mcColour == _player
            && ISINSIDE(cpOldSquare->mupChesspiece->mContinuation.mrcvcpGetList(), cpNewSquare)))
        // do something

Now, I call this function from the below piece of code. I introduced the rcOverride bool in order to optimise the _move function, because, logically speaking, all the conditions of the if statement were met when calling the function from this environment, so I did not need to test for those again.

for (const auto * const & rcpcChesspiece : _chessboard.mPieces.mrcvcpGetList()) {
        if (rcpcChesspiece->mcColour != _player) continue;
        for (auto * const & rcpSquare : rcpcChesspiece->mContinuation.mrcvcpGetList())
            if (_move(rcpcChesspiece->mpSquare, rcpSquare, true))
                // do something
    }

I got a segfault, however, which I've been able to pinpoint to come from the third condition being untrue (the ISINSIDE macro, defined as #define ISINSIDE(x,y) (std::find(x.begin(), x.end(), y) != x.end())).

The programme behaves correctly if I remove the true override, allowing it to test for the third condition, and subsequently not run the code inside the if-statement.

You might not agree with the way I handled this optimisation effort, but looking at all the variables, where they come from (logically speaking -- take a look at the range-based for-loops in the second block of code), I must conclude that they should behave equivalently. ISINSIDE must always evaluate to true, right? Can you see where the difference in behaviour comes from?

Upvotes: 0

Views: 107

Answers (1)

Jeff Garrett
Jeff Garrett

Reputation: 7383

Unwrapping the boilerplate, the code is testing whether the container

rcpcChesspiece->mpSquare->mupChesspiece->mContinuation.mrcvcpGetList()

contains rcpSquare. By virtue of the range-for loop, we know that it should be contained in

rcpcChesspiece->mContinuation.mrcvcpGetList()

With the code presented, there is not enough information to conclude those containers must always be equal or that a member of one is always a member of the other.

Upvotes: 1

Related Questions