2016-10-25 6 views
7

Angenommen, ich habe eine std::tuple:Wie kann ich herausfinden, ob ein Element in einem Tupel existiert?

std::tuple<Types...> myTuple; 
// fill myTuple with stuff 

Jetzt will ich, wenn func kehrt gilt für jedes Element in der Lambda, wo func einige Lambda, zB:

auto func = [](auto&& x) -> bool { return someOperation(x); } 

Wie kann ich tun Dies? Beachten Sie, dass Types... möglicherweise groß ist, sodass ich nicht jedes Mal über alle Elemente iterieren möchte.

+0

Du könntest [den Tup auspacken le für den Aufruf einer variadic-template-Funktion] (http://stackoverflow.com/questions/687490/how-do-i-pand-a-tuple-into-variadic-template-functions-arguments), die jedes Argument überprüfen. –

+1

Scheint ein Duplikat von [dies] zu sein (http://stackoverflow.com/questions/1198260/iterate-over-tuple). – m8mble

+0

@ m8mble Ich habe eine Zeile hinzugefügt, um zu verdeutlichen, warum das anders ist (im Grunde ist es der Unterschied zwischen 'for_each' und' any_of' - stoppt auf dem Element, wenn Sie es finden). – arman

Antwort

4
#include <tuple> 

std::tuple<int, char, double> myTuple{ 1, 'a', 3.14f }; 

bool result = std::apply([](auto&&... args) { 
          return (someOperation(decltype(args)(args)) || ...); 
         } 
         , myTuple); 

DEMO

+0

in diesem Fall kann es nur 'args' sein, aber im Allgemeinen, wenn, sagen wir, würde man' std :: move (myTuple) 'in' apply' eingeben, dann glaube ich, Weiterleitung könnte nützlich sein –

+1

Ich würde das erwähnen ' std :: apply' ist C++ 17. – skypjack

+2

@skypjack also sind Falte Ausdrücke – krzaq

2

Hier ist eine C++ 14-Lösung:

template <typename Tuple, typename Pred> 
constexpr bool any_of_impl(Tuple const&, Pred&&, std::index_sequence<>) { 
    return false; 
} 

template <typename Tuple, typename Pred, size_t first, size_t... is> 
constexpr bool any_of_impl(Tuple const& t, Pred&& pred, std::index_sequence<first, is...>) { 
    return pred(std::get<first>(t)) || any_of_impl(t, std::forward<Pred>(pred), std::index_sequence<is...>{}); 
} 

template <typename... Elements, typename Pred, size_t... is> 
constexpr bool any_of(std::tuple<Elements...> const& t, Pred&& pred) { 
    return any_of_impl(t, std::forward<Pred>(pred), std::index_sequence_for<Elements...>{}); 
} 

live demo

+0

gute Lösung, aber ich bin mir nicht sicher, ob es irgendwelche Übersetzungszeit Boost von der Verwendung von 'std :: integer_sequence' ist, wie Sie' any_of_impl' für jeden Index von Tupel-Elementen instanziieren, nein? –

+0

@ W.F. Ich war im Begriff zu antworten, dass ich das brauche, weil Tupel Duplikate Typen haben und '' nicht funktionieren würde, aber mit diesem rekursiven Kurzschluss brauche ich das nicht. Ich werde mit einer besseren Version aktualisieren, danke. – krzaq

0

Und hier ist ein wenig retro C++ 11 Lösung:

#include <iostream> 
#include <tuple> 

template <class Tuple, class Lambda> 
bool any_of(Tuple &&tup, Lambda lambda, std::integral_constant<size_t, std::tuple_size<Tuple>::value> i) { 
    return false; 
} 

template <class Tuple, class Lambda, class I = std::integral_constant<size_t, 0>> 
bool any_of(Tuple &&tup, Lambda lambda, I i = {}) { 
    return lambda(std::forward<typename std::tuple_element<i, Tuple>::type>(std::get<i>(tup))) || 
      any_of(std::forward<Tuple>(tup), lambda, std::integral_constant<size_t, i+1>{}); 
} 

int main() { 
    std::cout << any_of(std::forward_as_tuple(1, 2, 3, 4), [](int&& i) { return i == 2; }) << std::endl; 
} 
Verwandte Themen