Search code examples
c++stl-algorithm

Can std::search_n be called with a count of 0?


Can std::search_n be called "safely" with a count of 0? Specifically, is code like the following valid?

#include <algorithm>
#include <cstdio>

int main(int argc, char *argv[]) {
    const int test[7] = {1, 2, 3, 4, 5, 6, 7};
    const int *const location = std::search_n(test, test + 7, 0, 8);
    if (location == test) {
        std::puts("Found it at the beginning!");
    }
}

I would expect this code to reach the std::puts statement, and most descriptions of std::search_n seem to imply that it will. However, most sample implementations that I'm finding won't. What sayeth the standard?


Solution

  • The specification of std::search_n is (§25.2.13 [alg.search]/p4-7):

    template<class ForwardIterator, class Size, class T,
    class BinaryPredicate>
    ForwardIterator
    search_n(ForwardIterator first, ForwardIterator last, Size count,
    const T& value, BinaryPredicate pred);
    

    4 Requires: The type Size shall be convertible to integral type (4.7, 12.3).

    5 Effects: Finds a subsequence of equal values in a sequence.

    6 Returns: The first iterator i in the range [first,last-count) such that for every non-negative integer n less than count the following corresponding conditions hold: *(i + n) == value, pred(*(i + n),value) != false. Returns last if no such iterator is found.

    7 Complexity: At most last - first applications of the corresponding predicate.

    When count <= 0, there is no non-negative integer n less than count, so the condition "for every* non-negative integer n less than count ..." is always true**, and so it should return the first iterator in range - which is first. Note that the spec implies that you are not allowed to pass a negative count if last-count isn't well-defined, but nothing in the spec prevents count from having a value of zero.

    All standard library implementations I tested (libstdc++, libc++, MSVC) print the message.


    *This used to be "for any...". LWG issue 2150 changed the wording here to clarify the intended meaning.

    **The statement "for every x in S, p" is vacuously true if S is an empty set.