summaryrefslogtreecommitdiff
path: root/boost/accumulators/framework/extractor.hpp
blob: 98281cecb9d9bb779917eccca2e2b1036fda188b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
///////////////////////////////////////////////////////////////////////////////
// extractor.hpp
//
//  Copyright 2005 Eric Niebler. Distributed under the Boost
//  Software License, Version 1.0. (See accompanying file
//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#ifndef BOOST_ACCUMULATORS_FRAMEWORK_EXTRACTOR_HPP_EAN_28_10_2005
#define BOOST_ACCUMULATORS_FRAMEWORK_EXTRACTOR_HPP_EAN_28_10_2005

#include <boost/preprocessor/tuple/rem.hpp>
#include <boost/preprocessor/array/size.hpp>
#include <boost/preprocessor/array/data.hpp>
#include <boost/preprocessor/array/elem.hpp>
#include <boost/preprocessor/seq/to_array.hpp>
#include <boost/preprocessor/seq/transform.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
#include <boost/parameter/binding.hpp>
#include <boost/mpl/apply.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/accumulators/accumulators_fwd.hpp>
#include <boost/accumulators/framework/parameters/accumulator.hpp>

namespace boost { namespace accumulators
{

namespace detail
{
    template<typename AccumulatorSet, typename Feature>
    struct accumulator_set_result
    {
        typedef typename as_feature<Feature>::type feature_type;
        typedef typename mpl::apply<AccumulatorSet, feature_type>::type::result_type type;
    };

    template<typename Args, typename Feature>
    struct argument_pack_result
      : accumulator_set_result<
            typename remove_reference<
                typename parameter::binding<Args, tag::accumulator>::type
            >::type
          , Feature
        >
    {
    };

    template<typename A, typename Feature>
    struct extractor_result
      : mpl::eval_if<
            detail::is_accumulator_set<A>
          , accumulator_set_result<A, Feature>
          , argument_pack_result<A, Feature>
        >
    {
    };

    template<typename Feature, typename AccumulatorSet>
    typename extractor_result<AccumulatorSet, Feature>::type
    do_extract(AccumulatorSet const &acc, mpl::true_)
    {
        typedef typename as_feature<Feature>::type feature_type;
        return extract_result<feature_type>(acc);
    }

    template<typename Feature, typename Args>
    typename extractor_result<Args, Feature>::type
    do_extract(Args const &args, mpl::false_)
    {
        typedef typename as_feature<Feature>::type feature_type;
        return find_accumulator<feature_type>(args[accumulator]).result(args);
    }

} // namespace detail


///////////////////////////////////////////////////////////////////////////////
/// Extracts the result associated with Feature from the specified accumulator_set.
template<typename Feature>
struct extractor
{
    typedef extractor<Feature> this_type;

    /// The result meta-function for determining the return type of the extractor
    template<typename F>
    struct result;

    template<typename A1>
    struct result<this_type(A1)>
      : detail::extractor_result<A1, Feature>
    {
    };

    /// Extract the result associated with Feature from the accumulator set
    /// \param acc The accumulator set object from which to extract the result
    template<typename Arg1>
    typename detail::extractor_result<Arg1, Feature>::type
    operator ()(Arg1 const &arg1) const
    {
        // Arg1 could be an accumulator_set or an argument pack containing
        // an accumulator_set. Dispatch accordingly.
        return detail::do_extract<Feature>(arg1, detail::is_accumulator_set<Arg1>());
    }

    /// \overload
    ///
    /// \param a1 Optional named parameter to be passed to the accumulator's result() function.
    template<typename AccumulatorSet, typename A1>
    typename detail::extractor_result<AccumulatorSet, Feature>::type
    operator ()(AccumulatorSet const &acc, A1 const &a1) const
    {
        BOOST_MPL_ASSERT((detail::is_accumulator_set<AccumulatorSet>));
        typedef typename as_feature<Feature>::type feature_type;
        return extract_result<feature_type>(acc, a1);
    }

    // ... other overloads generated by Boost.Preprocessor:

    /// INTERNAL ONLY
    ///
#define BOOST_ACCUMULATORS_EXTRACTOR_FUN_OP(z, n, _)                                    \
    template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)>                                  \
    struct result<this_type(BOOST_PP_ENUM_PARAMS_Z(z, n, A))>                           \
      : detail::extractor_result<A1, Feature>                                           \
    {};                                                                                 \
    template<                                                                           \
        typename AccumulatorSet                                                         \
        BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A)                               \
    >                                                                                   \
    typename detail::extractor_result<AccumulatorSet, Feature>::type                    \
    operator ()(                                                                        \
        AccumulatorSet const &acc                                                       \
        BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a)                       \
    ) const                                                                             \
    {                                                                                   \
        BOOST_MPL_ASSERT((detail::is_accumulator_set<AccumulatorSet>));                 \
        typedef typename as_feature<Feature>::type feature_type;                        \
        return extract_result<feature_type>(acc BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a));\
    }

    BOOST_PP_REPEAT_FROM_TO(
        2
      , BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS)
      , BOOST_ACCUMULATORS_EXTRACTOR_FUN_OP
      , _
    )

    #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED
    /// \overload
    ///
    template<typename AccumulatorSet, typename A1, typename A2, ...>
    typename detail::extractor_result<AccumulatorSet, Feature>::type
    operator ()(AccumulatorSet const &acc, A1 const &a1, A2 const &a2, ...);
    #endif
};

/// INTERNAL ONLY
///
#define BOOST_ACCUMULATORS_ARRAY_REM(Array)                                                         \
    BOOST_PP_TUPLE_REM_CTOR(BOOST_PP_ARRAY_SIZE(Array), BOOST_PP_ARRAY_DATA(Array))

/// INTERNAL ONLY
///
#define BOOST_ACCUMULATORS_SEQ_REM(Seq)                                                             \
    BOOST_ACCUMULATORS_ARRAY_REM(BOOST_PP_SEQ_TO_ARRAY(Seq))

/// INTERNAL ONLY
///
#define BOOST_ACCUMULATORS_ARGS_OP(s, data, elem)                                                   \
    T ## s

/// INTERNAL ONLY
///
#define BOOST_ACCUMULATORS_PARAMS_OP(s, data, elem)                                                 \
    elem T ## s

/// INTERNAL ONLY
///
#define BOOST_ACCUMULATORS_MAKE_FEATURE(Tag, Feature, ParamsSeq)                                    \
    Tag::Feature<                                                                                   \
        BOOST_ACCUMULATORS_SEQ_REM(                                                                 \
            BOOST_PP_SEQ_TRANSFORM(BOOST_ACCUMULATORS_ARGS_OP, ~, ParamsSeq)                        \
        )                                                                                           \
    >

/// INTERNAL ONLY
///
#define BOOST_ACCUMULATORS_DEFINE_EXTRACTOR_FUN_IMPL(z, n, Tag, Feature, ParamsSeq)                 \
    template<                                                                                       \
        BOOST_ACCUMULATORS_SEQ_REM(                                                                 \
            BOOST_PP_SEQ_TRANSFORM(BOOST_ACCUMULATORS_PARAMS_OP, ~, ParamsSeq)                      \
        )                                                                                           \
      , typename Arg1                                                                               \
        BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A)                                           \
    >                                                                                               \
    typename boost::accumulators::detail::extractor_result<                                         \
        Arg1                                                                                        \
      , BOOST_ACCUMULATORS_MAKE_FEATURE(Tag, Feature, ParamsSeq)                                    \
    >::type                                                                                         \
    Feature(Arg1 const &arg1 BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a) )            \
    {                                                                                               \
        typedef BOOST_ACCUMULATORS_MAKE_FEATURE(Tag, Feature, ParamsSeq) feature_type;              \
        return boost::accumulators::extractor<feature_type>()(                                      \
            arg1 BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a));                                         \
    }

/// INTERNAL ONLY
///
#define BOOST_ACCUMULATORS_DEFINE_EXTRACTOR_FUN(z, n, _)                                            \
    BOOST_ACCUMULATORS_DEFINE_EXTRACTOR_FUN_IMPL(                                                   \
        z                                                                                           \
      , n                                                                                           \
      , BOOST_PP_ARRAY_ELEM(0, _)                                                                   \
      , BOOST_PP_ARRAY_ELEM(1, _)                                                                   \
      , BOOST_PP_ARRAY_ELEM(2, _)                                                                   \
    )

#define BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(Tag, Feature, ParamSeq)                                 \
    BOOST_PP_REPEAT(                                                                                \
        BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS)                                                   \
      , BOOST_ACCUMULATORS_DEFINE_EXTRACTOR_FUN                                                     \
      , (3, (Tag, Feature, ParamSeq))                                                               \
    )

}} // namespace boost::accumulators

#endif