Skip to content

Commit

Permalink
tuple_for_each(): Call visitor from start to end, not in reverse.
Browse files Browse the repository at this point in the history
The test now passes.
  • Loading branch information
murraycu committed Mar 2, 2016
1 parent 03a5727 commit 3de113f
Showing 1 changed file with 26 additions and 5 deletions.
31 changes: 26 additions & 5 deletions tuple-utils/tuple_for_each.h
Expand Up @@ -23,32 +23,53 @@ namespace tupleutils {

namespace detail {

template <template <typename> class T_visitor, std::size_t index,
template <template <typename> class T_visitor, std::size_t size_from_index,
typename... T_extras>
struct tuple_for_each_impl {
template <typename T>
static void
tuple_for_each(T&& t, T_extras&&... extras) {
//We use std::decay_t<> because tuple_size is not defined for references.
constexpr auto size = std::tuple_size<std::decay_t<T>>::value;
static_assert(size > 1, "size must be more than 0.");

constexpr auto index = size - size_from_index;
static_assert(index >= 0, "unexpected index.");

using element_type = typename std::tuple_element<index, std::decay_t<T>>::type;
T_visitor<element_type>::visit(std::get<index>(t), std::forward<T_extras>(extras)...);

tuple_for_each_impl<T_visitor, index - 1, T_extras...>::tuple_for_each(
tuple_for_each_impl<T_visitor, size_from_index - 1, T_extras...>::tuple_for_each(
std::forward<T>(t), std::forward<T_extras>(extras)...);
}
};

template <template <typename> class T_visitor, typename... T_extras>
struct tuple_for_each_impl<T_visitor, 0, T_extras...> {
struct tuple_for_each_impl<T_visitor, 1, T_extras...> {
template <typename T>
static void
tuple_for_each(T&& t, T_extras&&... extras) {
constexpr std::size_t index = 0;
//We use std::decay_t<> because tuple_size is not defined for references.
constexpr auto size = std::tuple_size<std::decay_t<T>>::value;
static_assert(size > 0, "size must be more than 0.");

constexpr auto index = size - 1;
static_assert(index > 0, "unexpected index.");

using element_type = typename std::tuple_element<index, std::decay_t<T>>::type;
T_visitor<element_type>::visit(std::get<index>(std::forward<T>(t)), std::forward<T_extras>(extras)...);
}
};

template <template <typename> class T_visitor, typename... T_extras>
struct tuple_for_each_impl<T_visitor, 0, T_extras...> {
template <typename T>
static void
tuple_for_each(T&& /* t */, T_extras&&... /* extras */) {
//Do nothing because the tuple has no elements.
}
};

} // detail namespace


Expand All @@ -73,7 +94,7 @@ tuple_for_each(T&& t, T_extras&&... extras) {
return;
}

detail::tuple_for_each_impl<T_visitor, size - 1, T_extras...>::tuple_for_each(
detail::tuple_for_each_impl<T_visitor, size, T_extras...>::tuple_for_each(
std::forward<T>(t), std::forward<T_extras>(extras)...);
}

Expand Down

0 comments on commit 3de113f

Please sign in to comment.