Created
June 23, 2016 02:54
-
-
Save cdacamar/cab95e07d31e3a6883422da33cd18221 to your computer and use it in GitHub Desktop.
std::find, but beefy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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