Wie kann ich bei der Verwendung des std::for_each-Algorithmus unterbrechen, wenn eine bestimmte Bedingung erfüllt ist?
Antworten
Zu viele Anzeigen?Sie können std::any_of (oder std::all_of oder std::none_of) z.B. wie folgt verwenden:
std::vector<int> a;
// ...
std::all_of(a.begin(), a.end(), [&](int val) {
// return false if you want to break, true otherwise
});
Dies ist jedoch eine verschwenderische Lösung (Rückgabewerte werden nicht wirklich für irgendetwas verwendet), und Sie sind besser dran, wenn Sie Ihre eigene Schleife schreiben.
Sie können verwenden std::find_if
Algorithmus, der anhält und den Iterator zum ersten Element zurückführt, auf das die Prädikatsbedingung angewendet wird true
. Ihr Prädikat sollte also so geändert werden, dass es einen Booleschen Wert als Fortsetzungs- bzw. Unterbrechungsbedingung zurückgibt.
Dies ist jedoch ein Hack, so dass Sie die Algorithmen verwenden können.
Eine andere Möglichkeit ist die Verwendung von BOOST_FOREACH.
Sie können die for_each() abbrechen, indem Sie eine Ausnahme von Ihrem Funktor auslösen. Dies ist jedoch oft keine gute Idee, und es gibt Alternativen.
Sie können den Zustand in Ihrem Funktor beibehalten. Wenn Sie die "Break"-Bedingung erkennen, setzen Sie einfach ein Flag in Ihrem Funktor und kehren dann bei jeder nachfolgenden Iteration einfach zurück, ohne die Aufgabe Ihres Funktors zu erfüllen. Natürlich wird dadurch die Iteration nicht gestoppt, was bei großen Sammlungen teuer sein kann, aber zumindest wird die Arbeit nicht mehr ausgeführt.
Wenn Ihre Sammlung sortiert ist, können Sie mit find() das Element finden, an dem Sie abbrechen wollen, und dann for_each von begin() bis zu dem von find() zurückgegebenen Element ausführen.
Schließlich können Sie eine for_each_if()
. Auch hier wird die Iteration nicht gestoppt, aber der Funktor, der die Arbeit verrichtet, wird nicht ausgewertet, wenn das Prädikat als falsch ausgewertet wird. Hier sind 2 Varianten von for_each_xxx()
einen, der einen Wert annimmt und die Arbeit ausführt, wenn operator==() zu true ausgewertet wird, und einen anderen, der zwei Funktoren annimmt; einen, der einen Vergleich ala find_if() durchführt, und den anderen, der die Arbeit ausführt, wenn der Vergleichsoperator zu true ausgewertet wird.
/* ---
For each
25.1.1
template< class InputIterator, class Function, class T>
Function for_each_equal(InputIterator first, InputIterator last, const T& value, Function f)
template< class InputIterator, class Function, class Predicate >
Function for_each_if(InputIterator first, InputIterator last, Predicate pred, Function f)
Requires:
T is of type EqualityComparable (20.1.1)
Effects:
Applies f to each dereferenced iterator i in the range [first, last) where one of the following conditions hold:
1: *i == value
2: pred(*i) != false
Returns:
f
Complexity:
At most last - first applications of f
--- */
template< class InputIterator, class Function, class Predicate >
Function for_each_if(InputIterator first,
InputIterator last,
Predicate pred,
Function f)
{
for( ; first != last; ++first)
{
if( pred(*first) )
f(*first);
}
return f;
};
template< class InputIterator, class Function, class T>
Function for_each_equal(InputIterator first,
InputIterator last,
const T& value,
Function f)
{
for( ; first != last; ++first)
{
if( *first == value )
f(*first);
}
return f;
};
- See previous answers
- Weitere Antworten anzeigen