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);
}
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
andB
are indeterminately sequenced: they may be performed in any order but may not overlap: eitherA
will be complete beforeB
, orB
will be complete beforeA
.
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.
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
, orInputIterator2
, 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With