@@ -37,7 +37,8 @@ struct ForEachType<Functor, FirstType, OtherTypes...>
3737 static void call (Args &&...args)
3838 {
3939 Functor::template call<FirstType>(args...);
40- ForEachType<Functor, OtherTypes...>::template call<Args...>(args...);
40+ ForEachType<Functor, OtherTypes...>::template call<Args...>(
41+ std::forward<Args>(args)...);
4142 }
4243};
4344
@@ -49,4 +50,121 @@ struct ForEachType<Functor>
4950 { /* no-op */
5051 }
5152};
53+
54+ namespace internal
55+ {
56+
57+ template <typename Functor, typename ... Tuples>
58+ struct ForEachTypeNestedImpl ;
59+
60+ // Functor::template call<std::tuple<Type1, Type2, Type3, ...>>(args...)
61+ template <typename Functor, typename FirstTuple, typename ... Tuples>
62+ struct ForEachTypeNestedImpl <Functor, FirstTuple, Tuples...>
63+ {
64+
65+ template <typename InnerFunctor, typename Tuple>
66+ struct ForEachType_Tuple ;
67+
68+ template <typename InnerFunctor, typename ... Types>
69+ struct ForEachType_Tuple <InnerFunctor, std::tuple<Types...>>
70+ {
71+ template <typename ... Args>
72+ static void call (Args &&...args)
73+ {
74+ ForEachType<InnerFunctor, Types...>::template call<Args...>(
75+ std::forward<Args>(args)...);
76+ }
77+ };
78+
79+ template <typename FirstType, typename Tuple>
80+ struct PrependToTuple ;
81+ template <typename FirstType, typename ... Othertypes>
82+ struct PrependToTuple <FirstType, std::tuple<Othertypes...>>
83+ {
84+ using type = std::tuple<FirstType, Othertypes...>;
85+ };
86+
87+ // transform the outer Functor such that the first type argument
88+ // FirstType is already specified
89+ template <typename FirstType>
90+ struct PartialApply
91+ {
92+ // RestType is a tuple
93+ // Args the function arguments
94+ template <typename RestTypes, typename ... Args>
95+ static void call (Args &&...args)
96+ {
97+ using concatenated_tuple_t =
98+ typename PrependToTuple<FirstType, RestTypes>::type;
99+ Functor::template call<concatenated_tuple_t , Args...>(
100+ std::forward<Args>(args)...);
101+ }
102+ };
103+
104+ struct Runner
105+ {
106+ template <typename Type1, typename ... Args>
107+ static void call (Args &&...args)
108+ {
109+ using partially_applied_t = PartialApply<Type1>;
110+ // recursive call
111+ ForEachTypeNestedImpl<partially_applied_t , Tuples...>::
112+ template call<Args...>(std::forward<Args>(args)...);
113+ }
114+ };
115+
116+ template <typename ... Args>
117+ static void call (Args &&...args)
118+ {
119+ // outer loop
120+ using foreach_t = ForEachType_Tuple<Runner, FirstTuple>;
121+ foreach_t ::template call<Args...>(std::forward<Args>(args)...);
122+ }
123+ };
124+
125+ template <typename Functor>
126+ struct ForEachTypeNestedImpl <Functor>
127+ {
128+ template <typename ... Args>
129+ static void call (Args &&...args)
130+ {
131+ Functor::template call<std::tuple<>, Args...>(
132+ std::forward<Args>(args)...);
133+ }
134+ };
135+ } // namespace internal
136+
137+ template <typename Functor, typename ... Tuples>
138+ struct ForEachTypeNested
139+ {
140+ template <typename InnerFunctor, typename Tuple>
141+ struct ApplyTupleAsTypes ;
142+
143+ template <typename InnerFunctor, typename ... Types>
144+ struct ApplyTupleAsTypes <InnerFunctor, std::tuple<Types...>>
145+ {
146+ template <typename ... Args>
147+ static void call (Args &&...args)
148+ {
149+ InnerFunctor::template call<Types...>(std::forward<Args>(args)...);
150+ }
151+ };
152+
153+ struct TupledFunctor
154+ {
155+ template <typename Tuple, typename ... Args>
156+ static void call (Args &&...args)
157+ {
158+ ApplyTupleAsTypes<Functor, Tuple>::template call<Args...>(
159+ std::forward<Args>(args)...);
160+ }
161+ };
162+
163+ template <typename ... Args>
164+ static void call (Args &&...args)
165+ {
166+ internal::ForEachTypeNestedImpl<TupledFunctor, Tuples...>::
167+ template call<Args...>(std::forward<Args>(args)...);
168+ }
169+ };
52170} // namespace auxiliary
0 commit comments