1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // extractor.hpp |
3 | // |
4 | // Copyright 2005 Eric Niebler. Distributed under the Boost |
5 | // Software License, Version 1.0. (See accompanying file |
6 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
7 | |
8 | #ifndef BOOST_ACCUMULATORS_FRAMEWORK_EXTRACTOR_HPP_EAN_28_10_2005 |
9 | #define |
10 | |
11 | #include <boost/preprocessor/cat.hpp> |
12 | #include <boost/preprocessor/tuple/rem.hpp> |
13 | #include <boost/preprocessor/array/size.hpp> |
14 | #include <boost/preprocessor/array/data.hpp> |
15 | #include <boost/preprocessor/array/elem.hpp> |
16 | #include <boost/preprocessor/seq/to_array.hpp> |
17 | #include <boost/preprocessor/seq/transform.hpp> |
18 | #include <boost/preprocessor/repetition/enum_params.hpp> |
19 | #include <boost/preprocessor/repetition/enum_trailing.hpp> |
20 | #include <boost/preprocessor/repetition/enum_trailing_params.hpp> |
21 | #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp> |
22 | #include <boost/preprocessor/repetition/repeat.hpp> |
23 | #include <boost/preprocessor/repetition/repeat_from_to.hpp> |
24 | #include <boost/parameter/binding.hpp> |
25 | #include <boost/mpl/bool.hpp> |
26 | #include <boost/mpl/if.hpp> |
27 | #include <boost/mpl/eval_if.hpp> |
28 | #include <boost/mpl/apply.hpp> |
29 | #include <boost/type_traits/remove_const.hpp> |
30 | #include <boost/type_traits/remove_reference.hpp> |
31 | #include <boost/accumulators/accumulators_fwd.hpp> |
32 | #include <boost/accumulators/framework/parameters/accumulator.hpp> |
33 | |
34 | namespace boost { namespace accumulators |
35 | { |
36 | |
37 | namespace detail |
38 | { |
39 | template<typename AccumulatorSet, typename Feature> |
40 | struct accumulator_set_result |
41 | { |
42 | typedef typename as_feature<Feature>::type feature_type; |
43 | typedef typename mpl::apply< |
44 | typename boost::remove_const< |
45 | typename boost::remove_reference<AccumulatorSet>::type |
46 | >::type |
47 | , feature_type |
48 | >::type::result_type type; |
49 | }; |
50 | |
51 | template<typename Args, typename Feature> |
52 | struct argument_pack_result |
53 | : accumulator_set_result< |
54 | typename boost::remove_reference< |
55 | typename parameter::binding< |
56 | typename boost::remove_const< |
57 | typename boost::remove_reference<Args>::type |
58 | >::type |
59 | , tag::accumulator |
60 | >::type |
61 | >::type |
62 | , Feature |
63 | > |
64 | { |
65 | }; |
66 | |
67 | template<typename A, typename Feature> |
68 | struct |
69 | : mpl::eval_if< |
70 | detail::is_accumulator_set<A> |
71 | , accumulator_set_result<A, Feature> |
72 | , argument_pack_result<A, Feature> |
73 | > |
74 | { |
75 | }; |
76 | |
77 | template<typename Feature, typename AccumulatorSet> |
78 | typename extractor_result<AccumulatorSet, Feature>::type |
79 | (AccumulatorSet const &acc, mpl::true_) |
80 | { |
81 | typedef typename as_feature<Feature>::type feature_type; |
82 | return extract_result<feature_type>(acc); |
83 | } |
84 | |
85 | template<typename Feature, typename Args> |
86 | typename extractor_result<Args, Feature>::type |
87 | (Args const &args, mpl::false_) |
88 | { |
89 | typedef typename as_feature<Feature>::type feature_type; |
90 | return find_accumulator<feature_type>(args[accumulator]).result(args); |
91 | } |
92 | |
93 | } // namespace detail |
94 | |
95 | |
96 | /////////////////////////////////////////////////////////////////////////////// |
97 | /// Extracts the result associated with Feature from the specified accumulator_set. |
98 | template<typename Feature> |
99 | struct |
100 | { |
101 | typedef extractor<Feature> ; |
102 | |
103 | /// The result meta-function for determining the return type of the extractor |
104 | template<typename F> |
105 | struct ; |
106 | |
107 | template<typename A1> |
108 | struct <this_type(A1)> |
109 | : detail::extractor_result<A1, Feature> |
110 | { |
111 | }; |
112 | |
113 | /// Extract the result associated with Feature from the accumulator set |
114 | /// \param acc The accumulator set object from which to extract the result |
115 | template<typename Arg1> |
116 | typename detail::extractor_result<Arg1, Feature>::type |
117 | (Arg1 const &arg1) const |
118 | { |
119 | // Arg1 could be an accumulator_set or an argument pack containing |
120 | // an accumulator_set. Dispatch accordingly. |
121 | return detail::do_extract<Feature>(arg1, detail::is_accumulator_set<Arg1>()); |
122 | } |
123 | |
124 | /// \overload |
125 | /// |
126 | /// \param a1 Optional named parameter to be passed to the accumulator's result() function. |
127 | template<typename AccumulatorSet, typename A1> |
128 | typename detail::extractor_result<AccumulatorSet, Feature>::type |
129 | (AccumulatorSet const &acc, A1 const &a1) const |
130 | { |
131 | BOOST_MPL_ASSERT((detail::is_accumulator_set<AccumulatorSet>)); |
132 | typedef typename as_feature<Feature>::type feature_type; |
133 | return extract_result<feature_type>(acc, a1); |
134 | } |
135 | |
136 | // ... other overloads generated by Boost.Preprocessor: |
137 | |
138 | /// INTERNAL ONLY |
139 | /// |
140 | #define (z, n, _) \ |
141 | template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \ |
142 | struct <this_type(BOOST_PP_ENUM_PARAMS_Z(z, n, A))> \ |
143 | : detail::extractor_result<A1, Feature> \ |
144 | {}; \ |
145 | template< \ |
146 | typename AccumulatorSet \ |
147 | BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A) \ |
148 | > \ |
149 | typename detail::extractor_result<AccumulatorSet, Feature>::type \ |
150 | operator ()( \ |
151 | AccumulatorSet const &acc \ |
152 | BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a) \ |
153 | ) const \ |
154 | { \ |
155 | BOOST_MPL_ASSERT((detail::is_accumulator_set<AccumulatorSet>)); \ |
156 | typedef typename as_feature<Feature>::type feature_type; \ |
157 | return extract_result<feature_type>(acc BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a));\ |
158 | } |
159 | |
160 | BOOST_PP_REPEAT_FROM_TO( |
161 | 2 |
162 | , BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS) |
163 | , BOOST_ACCUMULATORS_EXTRACTOR_FUN_OP |
164 | , _ |
165 | ) |
166 | |
167 | #undef BOOST_ACCUMULATORS_EXTRACTOR_FUN_OP |
168 | |
169 | #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED |
170 | /// \overload |
171 | /// |
172 | template<typename AccumulatorSet, typename A1, typename A2, ...> |
173 | typename detail::extractor_result<AccumulatorSet, Feature>::type |
174 | operator ()(AccumulatorSet const &acc, A1 const &a1, A2 const &a2, ...); |
175 | #endif |
176 | }; |
177 | |
178 | }} // namespace boost::accumulators |
179 | |
180 | /// INTERNAL ONLY |
181 | /// |
182 | #define BOOST_ACCUMULATORS_ARRAY_REM(Array) \ |
183 | BOOST_PP_TUPLE_REM_CTOR(BOOST_PP_ARRAY_SIZE(Array), BOOST_PP_ARRAY_DATA(Array)) |
184 | |
185 | /// INTERNAL ONLY |
186 | /// |
187 | #define BOOST_ACCUMULATORS_SEQ_REM(Seq) \ |
188 | BOOST_ACCUMULATORS_ARRAY_REM(BOOST_PP_SEQ_TO_ARRAY(Seq)) |
189 | |
190 | /// INTERNAL ONLY |
191 | /// |
192 | #define BOOST_ACCUMULATORS_ARGS_OP(s, data, elem) \ |
193 | T ## s |
194 | |
195 | /// INTERNAL ONLY |
196 | /// |
197 | #define BOOST_ACCUMULATORS_PARAMS_OP(s, data, elem) \ |
198 | elem T ## s |
199 | |
200 | /// INTERNAL ONLY |
201 | /// |
202 | #define BOOST_ACCUMULATORS_MAKE_FEATURE(Tag, Feature, ParamsSeq) \ |
203 | Tag::Feature< \ |
204 | BOOST_ACCUMULATORS_SEQ_REM( \ |
205 | BOOST_PP_SEQ_TRANSFORM(BOOST_ACCUMULATORS_ARGS_OP, ~, ParamsSeq) \ |
206 | ) \ |
207 | > |
208 | |
209 | /// INTERNAL ONLY |
210 | /// |
211 | #define (z, n, Tag, Feature, ParamsSeq) \ |
212 | template< \ |
213 | BOOST_ACCUMULATORS_SEQ_REM( \ |
214 | BOOST_PP_SEQ_TRANSFORM(BOOST_ACCUMULATORS_PARAMS_OP, ~, ParamsSeq) \ |
215 | ) \ |
216 | , typename Arg1 \ |
217 | BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A) \ |
218 | > \ |
219 | typename boost::accumulators::detail::extractor_result< \ |
220 | Arg1 \ |
221 | , BOOST_ACCUMULATORS_MAKE_FEATURE(Tag, Feature, ParamsSeq) \ |
222 | >::type \ |
223 | Feature(Arg1 const &arg1 BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a) ) \ |
224 | { \ |
225 | typedef BOOST_ACCUMULATORS_MAKE_FEATURE(Tag, Feature, ParamsSeq) feature_type; \ |
226 | return boost::accumulators::extractor<feature_type>()( \ |
227 | arg1 BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a)); \ |
228 | } |
229 | |
230 | /// INTERNAL ONLY |
231 | /// |
232 | #define (z, n, _) \ |
233 | BOOST_ACCUMULATORS_DEFINE_EXTRACTOR_FUN_IMPL( \ |
234 | z \ |
235 | , n \ |
236 | , BOOST_PP_ARRAY_ELEM(0, _) \ |
237 | , BOOST_PP_ARRAY_ELEM(1, _) \ |
238 | , BOOST_PP_ARRAY_ELEM(2, _) \ |
239 | ) |
240 | |
241 | #define (Tag, Feature, ParamSeq) \ |
242 | BOOST_PP_REPEAT( \ |
243 | BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS) \ |
244 | , BOOST_ACCUMULATORS_DEFINE_EXTRACTOR_FUN \ |
245 | , (3, (Tag, Feature, ParamSeq)) \ |
246 | ) |
247 | |
248 | #endif |
249 | |