]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | //////////////////////////////////////////////////////////////////////////// |
2 | // lazy smart.hpp | |
3 | // | |
4 | // Build lazy functoid traits for Phoenix equivalents for FC++ | |
5 | // | |
6 | // These are equivalents of the Boost FC++ functoid traits in smart.hpp | |
7 | // | |
8 | // I have copied the versions for zero, one, two and three arguments. | |
9 | // | |
10 | /*============================================================================= | |
11 | Copyright (c) 2000-2003 Brian McNamara and Yannis Smaragdakis | |
12 | Copyright (c) 2001-2007 Joel de Guzman | |
13 | Copyright (c) 2015 John Fletcher | |
14 | ||
15 | Distributed under the Boost Software License, Version 1.0. (See accompanying | |
16 | file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
17 | ==============================================================================*/ | |
18 | ||
19 | #ifndef BOOST_PHOENIX_FUNCTION_LAZY_SMART | |
20 | #define BOOST_PHOENIX_FUNCTION_LAZY_SMART | |
21 | ||
22 | namespace boost { | |
23 | namespace phoenix { | |
24 | namespace fcpp { | |
25 | ||
26 | ////////////////////////////////////////////////////////////////////// | |
27 | // Feature: Smartness | |
28 | ////////////////////////////////////////////////////////////////////// | |
29 | // If F is smart, then we can refer to these entities: | |
30 | // | |
31 | // functoid_traits<F>::template accepts<N>::args | |
32 | // A bool which says whether F can accept N arguments | |
33 | // | |
34 | // functoid_traits<F>::max_args | |
35 | // An int which says what the most arguments F can accept is | |
36 | // | |
37 | // functoid_traits<F>::template ensure_accepts<N>::args() | |
38 | // A no-op call that compiles only if F can accept N args | |
39 | // | |
40 | // We use traits so that if you happen to ask a non-smart functoid these | |
41 | // questions, you will hopefully get a literate error message. | |
42 | ||
43 | struct SmartFunctoid {}; | |
44 | ||
45 | // We add crazy identifiers to ensure that users don't accidentally talk | |
46 | // to functoids directly; they should always be going through the traits | |
47 | // class to ask for info. | |
48 | struct smart_functoid0 : public SmartFunctoid { | |
49 | template <class Dummy, int i> struct crazy_accepts { | |
50 | static const bool args = false; | |
51 | }; | |
52 | template <class Dummy> struct crazy_accepts<Dummy,0> { | |
53 | static const bool args = true; | |
54 | }; | |
55 | static const int crazy_max_args = 0; | |
56 | }; | |
57 | ||
58 | struct smart_functoid1 : public SmartFunctoid { | |
59 | template <class Dummy, int i> struct crazy_accepts { | |
60 | static const bool args = false; | |
61 | }; | |
62 | template <class Dummy> struct crazy_accepts<Dummy,1> { | |
63 | static const bool args = true; | |
64 | }; | |
65 | static const int crazy_max_args = 1; | |
66 | }; | |
67 | ||
68 | struct smart_functoid2 : public SmartFunctoid { | |
69 | template <class Dummy, int i> struct crazy_accepts { | |
70 | static const bool args = false; | |
71 | }; | |
72 | template <class Dummy> struct crazy_accepts<Dummy,1> { | |
73 | static const bool args = true; | |
74 | }; | |
75 | template <class Dummy> struct crazy_accepts<Dummy,2> { | |
76 | static const bool args = true; | |
77 | }; | |
78 | static const int crazy_max_args = 2; | |
79 | }; | |
80 | ||
81 | struct smart_functoid3 : public SmartFunctoid { | |
82 | template <class Dummy, int i> struct crazy_accepts { | |
83 | static const bool args = false; | |
84 | }; | |
85 | template <class Dummy> struct crazy_accepts<Dummy,1> { | |
86 | static const bool args = true; | |
87 | }; | |
88 | template <class Dummy> struct crazy_accepts<Dummy,2> { | |
89 | static const bool args = true; | |
90 | }; | |
91 | template <class Dummy> struct crazy_accepts<Dummy,3> { | |
92 | static const bool args = true; | |
93 | }; | |
94 | static const int crazy_max_args = 3; | |
95 | }; | |
96 | ||
97 | ||
98 | namespace impl { | |
99 | template <class F, bool b> struct NeededASmartFunctoidButInsteadGot {}; | |
100 | template <class F> struct NeededASmartFunctoidButInsteadGot<F,true> { | |
101 | typedef F type; | |
102 | }; | |
103 | template <bool b> struct Ensure; | |
104 | template <> struct Ensure<true> {}; | |
105 | } // end namespace impl | |
106 | ||
107 | template <class MaybeASmartFunctoid> | |
108 | struct functoid_traits { | |
109 | typedef typename boost::remove_reference<MaybeASmartFunctoid>::type MaybeASmartFunctoidT; | |
110 | typedef | |
111 | typename impl::NeededASmartFunctoidButInsteadGot<MaybeASmartFunctoidT, | |
112 | boost::is_base_and_derived<SmartFunctoid, | |
113 | MaybeASmartFunctoidT>::value>::type F; | |
114 | template <int i> struct accepts { | |
115 | static const bool args = F::template crazy_accepts<int,i>::args; | |
116 | }; | |
117 | template <int i> struct ensure_accepts { | |
118 | static const bool ok = F::template crazy_accepts<int,i>::args; | |
119 | inline static void args() { (void) impl::Ensure<ok>(); } | |
120 | }; | |
121 | static const int max_args = F::crazy_max_args; | |
122 | }; | |
123 | ||
124 | // These can be used to make functoids smart without having to alter | |
125 | // code elsewhere. These are used instead of boost::phoenix::function | |
126 | // to declare the object. | |
127 | template <typename F> | |
128 | struct smart_function0 : public smart_functoid0, | |
129 | public boost::phoenix::function<F> | |
130 | { }; | |
131 | ||
132 | template <typename F> | |
133 | struct smart_function1 : public smart_functoid1, | |
134 | public boost::phoenix::function<F> | |
135 | { | |
136 | typedef F type; | |
137 | }; | |
138 | ||
139 | template <typename F> | |
140 | struct smart_function2 : public smart_functoid2, | |
141 | public boost::phoenix::function<F> | |
142 | { }; | |
143 | ||
144 | template <typename F> | |
145 | struct smart_function3 : public smart_functoid3, | |
146 | public boost::phoenix::function<F> | |
147 | { }; | |
148 | } | |
149 | } | |
150 | } | |
151 | ||
152 | ||
153 | #endif |