Skip to content

Instantly share code, notes, and snippets.

@cdacamar
Created June 23, 2016 02:54
Show Gist options
  • Save cdacamar/cab95e07d31e3a6883422da33cd18221 to your computer and use it in GitHub Desktop.
Save cdacamar/cab95e07d31e3a6883422da33cd18221 to your computer and use it in GitHub Desktop.
std::find, but beefy
#include <array> // std::array
#include <iostream> // std::cout
#include <iterator> // std::begin, std::end, std::distance
#include <tuple> // std::tuple
#include <type_traits> // std::decay_t
#include <utility> // std::integer_sequence, std::forward
#include <vector> // std::vector
namespace detail
{
template <typename T, std::size_t... Ints>
auto init_array_helper(const T& x, std::index_sequence<Ints...>) {
using arr_t = std::array<std::decay_t<T>, std::index_sequence<Ints...>::size()>;
return arr_t{ (Ints, x)... };
}
template <std::size_t N, typename T>
auto initialize_array(T&& x) {
return init_array_helper(std::forward<T>(x), std::make_index_sequence<N>{});
}
template <typename Itr, typename F>
bool apply_match(Itr first, Itr last, Itr& x, F&& fn) {
if (x != last) return true;
if (fn(*first)) {
x = first;
return true;
}
return false;
}
template <typename Itr, typename Arr, typename Tuple, std::size_t... Ints>
bool find_matches(Itr first, Itr last, Arr& a, Tuple& t, std::index_sequence<Ints...>) {
bool done = true;
using swallow = int[];
(void)swallow{ (done &= apply_match(first, last, a[Ints], std::forward<decltype(std::get<Ints>(t))>(std::get<Ints>(t))), 0)... };
return done;
}
}
template <typename Itr, typename... Fns>
auto find_for_each(Itr first, Itr last, Fns&&... fns) {
auto fn_tup = std::make_tuple(std::forward<Fns>(fns)...);
auto result = detail::initialize_array<sizeof...(fns)>(last);
auto seq = std::make_index_sequence<sizeof...(fns)>{};
while ((first != last) && !detail::find_matches(first++, last, result, fn_tup, seq));
return result;
}
int main() {
std::vector<int> v {1,2,3,4,5,6,6,7,8,98};
auto result = find_for_each(std::begin(v), std::end(v),
[](int x)->bool {
return x == 6;
},
[](int x)->bool {
return x == 7;
},
[](int x)->bool {
return x > 4;
});
std::cout<<"indexes: ";
for (auto it : result) std::cout<<std::distance(std::begin(v), it)<<',';
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment