• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
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 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
do_extract(AccumulatorSet const & acc,mpl::true_)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
do_extract(Args const & args,mpl::false_)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.
98 template<typename Feature>
99 struct 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
operator ()boost::accumulators::extractor117     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
operator ()boost::accumulators::extractor129     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