1 /* Copyright (C) 2016 Murray Cumming
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/
17 #ifndef SIGC_TUPLE_UTILS_TUPLE_FOR_EACH_H
18 #define SIGC_TUPLE_UTILS_TUPLE_FOR_EACH_H
28 template <template <typename> class T_visitor, std::size_t size_from_index,
30 struct tuple_for_each_impl {
35 tuple_for_each(T&& t, T_extras&&... extras) {
36 //We use std::decay_t<> because tuple_size is not defined for references.
37 constexpr auto size = std::tuple_size<std::decay_t<T>>::value;
38 static_assert(size > 1, "size must be more than 0.");
40 constexpr auto index = size - size_from_index;
41 static_assert(index >= 0, "unexpected index.");
43 using element_type = typename std::tuple_element<index, std::decay_t<T>>::type;
44 T_visitor<element_type>::visit(std::get<index>(t), std::forward<T_extras>(extras)...);
46 tuple_for_each_impl<T_visitor, size_from_index - 1, T_extras...>::tuple_for_each(
47 std::forward<T>(t), std::forward<T_extras>(extras)...);
51 template <template <typename> class T_visitor, typename... T_extras>
52 struct tuple_for_each_impl<T_visitor, 1, T_extras...> {
57 tuple_for_each(T&& t, T_extras&&... extras) {
58 //We use std::decay_t<> because tuple_size is not defined for references.
59 constexpr auto size = std::tuple_size<std::decay_t<T>>::value;
60 static_assert(size > 0, "size must be more than 0.");
62 constexpr auto index = size - 1;
63 static_assert(index >= 0, "unexpected index.");
65 using element_type = typename std::tuple_element<index, std::decay_t<T>>::type;
66 T_visitor<element_type>::visit(std::get<index>(std::forward<T>(t)), std::forward<T_extras>(extras)...);
70 template <template <typename> class T_visitor, typename... T_extras>
71 struct tuple_for_each_impl<T_visitor, 0, T_extras...> {
76 tuple_for_each(T&& /* t */, T_extras&&... /* extras */) {
77 //Do nothing because the tuple has no elements.
85 * Call the @e T_Visitor functors visit() method for each element,
86 * from the first to the last.
88 * @tparam T_visitor should be a template that has a static visit() method.
89 * @tparam T the tuple type.
90 * @tparam T_extras the types of any extra arguments to pass to @e T_Visitor's
92 * @param t The tuple whose elements should be visited.
93 * @param extras Any extra arguments to pass to @e T_Visitor's visit() method.
95 template <template <typename> class T_visitor, typename T, typename... T_extras>
98 tuple_for_each(T&& t, T_extras&&... extras) {
99 //We use std::decay_t<> because tuple_size is not defined for references.
100 constexpr auto size = std::tuple_size<std::decay_t<T>>::value;
106 detail::tuple_for_each_impl<T_visitor, size, T_extras...>::tuple_for_each(
107 std::forward<T>(t), std::forward<T_extras>(extras)...);
110 } // namespace internal
114 #endif //SIGC_TUPLE_UTILS_TUPLE_FOR_EACH_H