Search code examples
c++c++11comparisonlanguage-lawyer

Is std::equal guaranteed to short circuit?


I would like to compare a nul-terminated string against a string literal. I hope to use std::equal and am curious if this code is well-defined according to the C++ standard:

#include <algorithm>

bool is_foo(const char *str) {
    const char *lit = "foo";
    return std::equal(lit, lit + 4, str);
}

If std::equal is guaranteed to stop at the first mismatch, then this code seems defined to me even if str has length < 3. If there is no such guarantee then I think this may dereference past the end of str resulting in UB.

What if anything does the C++ spec say about this? Thanks for any help!


Solution

  • My reading of the C++ standard indicates that this is pedantically undefined behavior based on the following remark:

    Remarks: If last2 was not given in the argument list, it denotes first2 + (last1 - first1) below.

    This is referring to overloads of std::equal that do not supply the second sequence's ending iterator. In this case this would not be a valid pointer, hence this is pedantically undefined behavior, given the following part of the specification:

    E be: pred(*i, *(first2 + (i - first1))) for the overloads with no parameter proj1;

    ...

    Returns: If last1 - first1 != last2 - first2, return false. Otherwise return true if E holds for every iterator i in the range [first1, last1) Otherwise, returns false.

    I see nothing here that guarantees short circuit evaluation. The complexity does not seem to imply guaranteed short-circuit evaluation, either:

    Complexity:

    [ ... ]

    ... at most min(last1 - first1, last2 - first2) applications of ...

    The "at most" part is not qualified in any way. Strictly interpreted this allows, but not requires, short-circuit evaluation.