Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does std::any_of guarantee the order of iteration when used with sequencial execution policy?

Tags:

c++

std

I have a list of filter functions. If any of these functions return 'true', I should not process an event further.

std::any_of seems suitable for this use case, but I wish to guarantee that the filter functions are called in the order they have been appended to my list (because of possible side effects they may have). Therefore, if I use std::any_of, I need to know the order it calls the filter functions is deterministic, from begin() to end() of the list.

I have checked the C++ standard on std::any_of and the sequential execution policy, but found no mention of order guarantees. I did not find mention about order guarantees on cppreference, and did not find an answered question similar enough on stackoverflow.

My conclusion is that there are no order guarantees. Although most compilers will probably process the functions in my in order, I should not rely on it.

bool MyClass::event(QEvent* event)
{
    std::vector<std::function<bool(QEvent*)> > functionList = getCurrentEventFilters();

    const auto bFilter = std::any_of(functionList .begin(),
                                     functionList .end(),
                                     [&event](std::function<bool(QEvent*)> function) {return function(event);});
    if (bFilter)
    {
        return true;
    }

    return Base::event(event);
}
like image 810
Asperamanca Avatar asked Aug 21 '19 09:08

Asperamanca


2 Answers

regarding std::execution::sequenced_policy:

The invocations of element access functions in parallel algorithms invoked with this policy (usually specified as std::execution::seq) are indeterminately sequenced in the calling thread.

regarding indeterminately-sequenced:

evaluations of A and B are indeterminately sequenced: they may be performed in any order but may not overlap: either A will be complete before B, or B will be complete before A.

To me this seems like explicit statement that you cant rely on order of things.
I didnt expect this..

In principle it should not matter to you though. It seems dubious to call std::any_of or std::all_of on something with side effects.

like image 57
user1316208 Avatar answered Oct 06 '22 00:10

user1316208


You ask about sequential execution policy but call an overload where no policy is specified. These may differ, since the overload that accepts an execution policy requires ForwardIterator while the other one requires InputIterator: http://eel.is/c++draft/alg.any.of.

The Standard then says here: http://eel.is/c++draft/algorithms.requirements#4.1:

If an algorithm's template parameter is named InputIterator, InputIterator1, or InputIterator2, the template argument shall meet the Cpp17InputIterator requirements.

This basically means that the implementation may only increment the input iterator and the range will be processed in order.

On the contrary, I am not sure whether the implementation may or may not provide an additional algorithm version for some other type of iterator, such as the random-access one.

A relevant question: Why std::transform doesn't guarantee the order (but for_each guarantee the order)? Doesn't this allow trick implementation for performance?. One comment there says:

The implementation is free to detect stronger iterator strengths and apply a different (possibly out-of-order) algorithm.

Though there is some discussion about it. If it is true, the order is guaranteed only if the iterator is of input type.

like image 41
Daniel Langr Avatar answered Oct 05 '22 23:10

Daniel Langr