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 BOOST_ACCUMULATORS_FRAMEWORK_EXTRACTOR_HPP_EAN_28_10_2005
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
34namespace boost { namespace accumulators
35{
36
37namespace 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 extractor_result
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 do_extract(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 do_extract(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.
98template<typename Feature>
99struct extractor
100{
101 typedef extractor<Feature> this_type;
102
103 /// The result meta-function for determining the return type of the extractor
104 template<typename F>
105 struct result;
106
107 template<typename A1>
108 struct result<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 operator ()(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 operator ()(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 BOOST_ACCUMULATORS_EXTRACTOR_FUN_OP(z, n, _) \
141 template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
142 struct result<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 BOOST_ACCUMULATORS_DEFINE_EXTRACTOR_FUN_IMPL(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 BOOST_ACCUMULATORS_DEFINE_EXTRACTOR_FUN(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 BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(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

source code of include/boost/accumulators/framework/extractor.hpp