2016-10-25 4 views
7

Предположим, у меня есть std::tuple:Как узнать, существует ли элемент в кортеже?

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

Теперь я хочу, чтобы найти, если func возвращает верно для любого элемента в лямбда, где func некоторая лямбда, например:

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

Как я могу сделать это? Обратите внимание, что Types... может быть большим, поэтому я не хочу перебирать все элементов каждый раз.

+0

Вы можете распаковать tup le для вызова функции varadic-template] (http://stackoverflow.com/questions/687490/how-do-i-expand-a-tuple-into-variadic-template-functions-arguments), которые проверяют каждый аргумент. –

+1

Кажется, это дубликат [this] (http://stackoverflow.com/questions/1198260/iterate-over-tuple). – m8mble

+0

@ m8mble Я добавил строку, чтобы подчеркнуть, почему это другое (в основном это разница между 'for_each' и' any_of' - остановкой элемента, когда вы его находите). – arman

ответ

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

, в этом случае это может быть просто 'args', но в общем случае, если, скажем, вы бы набрали' std :: move (myTuple) 'в' apply', тогда я считаю, что пересылка может быть полезна –

+1

Я бы упомянул, что ' std :: apply' - это C++ 17. – skypjack

+2

@skypjack - это выражения сгиба – krzaq

2

Вот C++ 14 раствор:

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

хорошее решение, но я не уверен, есть ли время слияния с использованием 'std :: integer_sequence', поскольку вы создаете экземпляр' any_of_impl' для каждого индекса элементов кортежа, нет? –

+0

@ W.F. Я собирался ответить, что мне нужно это, потому что кортеж может иметь дублированные типы, а 'get ' не будет работать, но с этим рекурсивным короткозамкнутым я не нуждаюсь в этом. Спасибо, спасибо. – krzaq

0

А вот немного ретро C++ 11 Решение:

#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; 
} 
Смежные вопросы