|
1 // Boost Lambda Library - lambda_functors.hpp ------------------------------- |
|
2 |
|
3 // Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi) |
|
4 // |
|
5 // Distributed under the Boost Software License, Version 1.0. (See |
|
6 // accompanying file LICENSE_1_0.txt or copy at |
|
7 // http://www.boost.org/LICENSE_1_0.txt) |
|
8 // |
|
9 // For more information, see http://www.boost.org |
|
10 |
|
11 // ------------------------------------------------ |
|
12 |
|
13 #ifndef BOOST_LAMBDA_LAMBDA_FUNCTORS_HPP |
|
14 #define BOOST_LAMBDA_LAMBDA_FUNCTORS_HPP |
|
15 |
|
16 namespace boost { |
|
17 namespace lambda { |
|
18 |
|
19 // -- lambda_functor -------------------------------------------- |
|
20 // -------------------------------------------------------------- |
|
21 |
|
22 //inline const null_type const_null_type() { return null_type(); } |
|
23 |
|
24 namespace detail { |
|
25 namespace { |
|
26 |
|
27 static const null_type constant_null_type = null_type(); |
|
28 |
|
29 } // unnamed |
|
30 } // detail |
|
31 |
|
32 class unused {}; |
|
33 |
|
34 #define cnull_type() detail::constant_null_type |
|
35 |
|
36 // -- free variables types -------------------------------------------------- |
|
37 |
|
38 // helper to work around the case where the nullary return type deduction |
|
39 // is always performed, even though the functor is not nullary |
|
40 namespace detail { |
|
41 template<int N, class Tuple> struct get_element_or_null_type { |
|
42 typedef typename |
|
43 detail::tuple_element_as_reference<N, Tuple>::type type; |
|
44 }; |
|
45 template<int N> struct get_element_or_null_type<N, null_type> { |
|
46 typedef null_type type; |
|
47 }; |
|
48 } |
|
49 |
|
50 template <int I> struct placeholder; |
|
51 |
|
52 template<> struct placeholder<FIRST> { |
|
53 |
|
54 template<class SigArgs> struct sig { |
|
55 typedef typename detail::get_element_or_null_type<0, SigArgs>::type type; |
|
56 }; |
|
57 |
|
58 template<class RET, CALL_TEMPLATE_ARGS> |
|
59 RET call(CALL_FORMAL_ARGS) const { |
|
60 BOOST_STATIC_ASSERT(boost::is_reference<RET>::value); |
|
61 CALL_USE_ARGS; // does nothing, prevents warnings for unused args |
|
62 return a; |
|
63 } |
|
64 }; |
|
65 |
|
66 template<> struct placeholder<SECOND> { |
|
67 |
|
68 template<class SigArgs> struct sig { |
|
69 typedef typename detail::get_element_or_null_type<1, SigArgs>::type type; |
|
70 }; |
|
71 |
|
72 template<class RET, CALL_TEMPLATE_ARGS> |
|
73 RET call(CALL_FORMAL_ARGS) const { CALL_USE_ARGS; return b; } |
|
74 }; |
|
75 |
|
76 template<> struct placeholder<THIRD> { |
|
77 |
|
78 template<class SigArgs> struct sig { |
|
79 typedef typename detail::get_element_or_null_type<2, SigArgs>::type type; |
|
80 }; |
|
81 |
|
82 template<class RET, CALL_TEMPLATE_ARGS> |
|
83 RET call(CALL_FORMAL_ARGS) const { CALL_USE_ARGS; return c; } |
|
84 }; |
|
85 |
|
86 template<> struct placeholder<EXCEPTION> { |
|
87 |
|
88 template<class SigArgs> struct sig { |
|
89 typedef typename detail::get_element_or_null_type<3, SigArgs>::type type; |
|
90 }; |
|
91 |
|
92 template<class RET, CALL_TEMPLATE_ARGS> |
|
93 RET call(CALL_FORMAL_ARGS) const { CALL_USE_ARGS; return env; } |
|
94 }; |
|
95 |
|
96 typedef const lambda_functor<placeholder<FIRST> > placeholder1_type; |
|
97 typedef const lambda_functor<placeholder<SECOND> > placeholder2_type; |
|
98 typedef const lambda_functor<placeholder<THIRD> > placeholder3_type; |
|
99 |
|
100 |
|
101 /////////////////////////////////////////////////////////////////////////////// |
|
102 |
|
103 |
|
104 // free variables are lambda_functors. This is to allow uniform handling with |
|
105 // other lambda_functors. |
|
106 // ------------------------------------------------------------------- |
|
107 |
|
108 |
|
109 |
|
110 // -- lambda_functor NONE ------------------------------------------------ |
|
111 template <class T> |
|
112 class lambda_functor : public T |
|
113 { |
|
114 |
|
115 BOOST_STATIC_CONSTANT(int, arity_bits = get_arity<T>::value); |
|
116 |
|
117 public: |
|
118 typedef T inherited; |
|
119 |
|
120 lambda_functor() {} |
|
121 lambda_functor(const lambda_functor& l) : inherited(l) {} |
|
122 |
|
123 lambda_functor(const T& t) : inherited(t) {} |
|
124 |
|
125 template <class SigArgs> struct sig { |
|
126 typedef typename inherited::template |
|
127 sig<typename SigArgs::tail_type>::type type; |
|
128 }; |
|
129 |
|
130 // Note that this return type deduction template is instantiated, even |
|
131 // if the nullary |
|
132 // operator() is not called at all. One must make sure that it does not fail. |
|
133 typedef typename |
|
134 inherited::template sig<null_type>::type |
|
135 nullary_return_type; |
|
136 |
|
137 nullary_return_type operator()() const { |
|
138 return inherited::template |
|
139 call<nullary_return_type> |
|
140 (cnull_type(), cnull_type(), cnull_type(), cnull_type()); |
|
141 } |
|
142 |
|
143 template<class A> |
|
144 typename inherited::template sig<tuple<A&> >::type |
|
145 operator()(A& a) const { |
|
146 return inherited::template call< |
|
147 typename inherited::template sig<tuple<A&> >::type |
|
148 >(a, cnull_type(), cnull_type(), cnull_type()); |
|
149 } |
|
150 |
|
151 template<class A, class B> |
|
152 typename inherited::template sig<tuple<A&, B&> >::type |
|
153 operator()(A& a, B& b) const { |
|
154 return inherited::template call< |
|
155 typename inherited::template sig<tuple<A&, B&> >::type |
|
156 >(a, b, cnull_type(), cnull_type()); |
|
157 } |
|
158 |
|
159 template<class A, class B, class C> |
|
160 typename inherited::template sig<tuple<A&, B&, C&> >::type |
|
161 operator()(A& a, B& b, C& c) const |
|
162 { |
|
163 return inherited::template call< |
|
164 typename inherited::template sig<tuple<A&, B&, C&> >::type |
|
165 >(a, b, c, cnull_type()); |
|
166 } |
|
167 |
|
168 // for internal calls with env |
|
169 template<CALL_TEMPLATE_ARGS> |
|
170 typename inherited::template sig<tuple<CALL_REFERENCE_TYPES> >::type |
|
171 internal_call(CALL_FORMAL_ARGS) const { |
|
172 return inherited::template |
|
173 call<typename inherited::template |
|
174 sig<tuple<CALL_REFERENCE_TYPES> >::type>(CALL_ACTUAL_ARGS); |
|
175 } |
|
176 |
|
177 template<class A> |
|
178 const lambda_functor<lambda_functor_base< |
|
179 other_action<assignment_action>, |
|
180 boost::tuple<lambda_functor, |
|
181 typename const_copy_argument <const A>::type> > > |
|
182 operator=(const A& a) const { |
|
183 return lambda_functor_base< |
|
184 other_action<assignment_action>, |
|
185 boost::tuple<lambda_functor, |
|
186 typename const_copy_argument <const A>::type> > |
|
187 ( boost::tuple<lambda_functor, |
|
188 typename const_copy_argument <const A>::type>(*this, a) ); |
|
189 } |
|
190 |
|
191 template<class A> |
|
192 const lambda_functor<lambda_functor_base< |
|
193 other_action<subscript_action>, |
|
194 boost::tuple<lambda_functor, |
|
195 typename const_copy_argument <const A>::type> > > |
|
196 operator[](const A& a) const { |
|
197 return lambda_functor_base< |
|
198 other_action<subscript_action>, |
|
199 boost::tuple<lambda_functor, |
|
200 typename const_copy_argument <const A>::type> > |
|
201 ( boost::tuple<lambda_functor, |
|
202 typename const_copy_argument <const A>::type>(*this, a ) ); |
|
203 } |
|
204 }; |
|
205 |
|
206 |
|
207 } // namespace lambda |
|
208 } // namespace boost |
|
209 |
|
210 #endif |
|
211 |
|
212 |