summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/metaparse/example/meta_hs/curry.hpp
blob: 5ca1711d37fc7bd5d594bdd202c849868f2b2cba (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
#ifndef BOOST_METAPARSE_META_HS_CURRY_HPP
#define BOOST_METAPARSE_META_HS_CURRY_HPP

// Copyright Abel Sinkovics (abel@sinkovics.hu)  2010.
// 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)

#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/equal_to.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/apply.hpp>
#include <boost/mpl/minus.hpp>
#include <boost/mpl/push_back.hpp>
#include <boost/mpl/unpack_args.hpp>
#include <boost/mpl/deque.hpp>
#include <boost/mpl/quote.hpp>

#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/tuple/eat.hpp>

#ifndef CURRY_MAX_ARGUMENT
#  define CURRY_MAX_ARGUMENT 5
#endif

namespace impl
{
  template <
    class UnpackedMetafunctionClass,
    class ArgumentsLeft,
    class ArgumentList
  >
  struct curry_impl;



  template <
    class UnpackedMetafunctionClass,
    class ArgumentsLeft,
    class ArgumentList
  >
  struct next_currying_step
  {
    typedef next_currying_step type;

    template <class T>
    struct apply :
      curry_impl<
        UnpackedMetafunctionClass,
        typename boost::mpl::minus<
          ArgumentsLeft,
          boost::mpl::int_<1>
        >::type,
        typename boost::mpl::push_back<ArgumentList, T>::type
      >
    {};
  };


  template <
    class UnpackedMetafunctionClass,
    class ArgumentsLeft,
    class ArgumentList
  >
  struct curry_impl :
    boost::mpl::eval_if<
      typename boost::mpl::equal_to<
        ArgumentsLeft,
        boost::mpl::int_<0>
      >::type,
      boost::mpl::apply<UnpackedMetafunctionClass, ArgumentList>,
      next_currying_step<
        UnpackedMetafunctionClass,
        ArgumentsLeft,
        ArgumentList
      >
    >
  {};
}


template <class T>
struct curry0 : T {};

#ifdef CURRY
#  error CURRY already defined
#endif
#define CURRY(z, n, unused) \
  template <template <BOOST_PP_ENUM(n,class BOOST_PP_TUPLE_EAT(3),~)> class T> \
  struct BOOST_PP_CAT(curry, n) : \
    impl::curry_impl< \
      boost::mpl::unpack_args<boost::mpl::BOOST_PP_CAT(quote, n) <T> >, \
      boost::mpl::int_<n>, \
      boost::mpl::deque<> \
    >::type \
  {};

BOOST_PP_REPEAT_FROM_TO(1, CURRY_MAX_ARGUMENT, CURRY, ~)

#undef CURRY

#endif