Chris@102
|
1 ////////////////////////////////////////////////////////////////////////////
|
Chris@102
|
2 // lazy_list.hpp
|
Chris@102
|
3 //
|
Chris@102
|
4 // Build lazy operations for Phoenix equivalents for FC++
|
Chris@102
|
5 //
|
Chris@102
|
6 // These are equivalents of the Boost FC++ functoids in list.hpp
|
Chris@102
|
7 //
|
Chris@102
|
8 // Implemented so far:
|
Chris@102
|
9 //
|
Chris@102
|
10 // head tail null
|
Chris@102
|
11 //
|
Chris@102
|
12 // strict_list<T> and associated iterator.
|
Chris@102
|
13 //
|
Chris@102
|
14 // list<T> and odd_list<T>
|
Chris@102
|
15 //
|
Chris@102
|
16 // cons cat
|
Chris@102
|
17 //
|
Chris@102
|
18 // Comparisons between list and odd_list types and separately for strict_list.
|
Chris@102
|
19 //
|
Chris@102
|
20 // NOTES: There is a fix at the moment as I have not yet sorted out
|
Chris@102
|
21 // how to get back the return type of a functor returning a list type.
|
Chris@102
|
22 // For the moment I have fixed this as odd_list<T> at two locations,
|
Chris@102
|
23 // one in list<T> and one in Cons. I am going to leave it like this
|
Chris@102
|
24 // for now as reading the code, odd_list<T> seems to be correct.
|
Chris@102
|
25 //
|
Chris@102
|
26 // I am also not happy at the details needed to detect types in Cons.
|
Chris@102
|
27 //
|
Chris@102
|
28 // I think the structure of this file is now complete.
|
Chris@102
|
29 // John Fletcher February 2015.
|
Chris@102
|
30 //
|
Chris@102
|
31 ////////////////////////////////////////////////////////////////////////////
|
Chris@102
|
32 /*=============================================================================
|
Chris@102
|
33 Copyright (c) 2000-2003 Brian McNamara and Yannis Smaragdakis
|
Chris@102
|
34 Copyright (c) 2001-2007 Joel de Guzman
|
Chris@102
|
35 Copyright (c) 2015 John Fletcher
|
Chris@102
|
36
|
Chris@102
|
37 Distributed under the Boost Software License, Version 1.0. (See accompanying
|
Chris@102
|
38 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@102
|
39 ==============================================================================*/
|
Chris@102
|
40
|
Chris@102
|
41 ///////////////////////////////////////////////////////////////////////
|
Chris@102
|
42 // This is from Boost FC++ list.hpp reimplemented without Fun0 or Full0
|
Chris@102
|
43 ///////////////////////////////////////////////////////////////////////
|
Chris@102
|
44
|
Chris@102
|
45 /*
|
Chris@102
|
46 concept ListLike: Given a list representation type L
|
Chris@102
|
47
|
Chris@102
|
48 L<T> inherits ListLike and has
|
Chris@102
|
49 // typedefs just show typical values
|
Chris@102
|
50 typedef T value_type
|
Chris@102
|
51 typedef L<T> force_result_type
|
Chris@102
|
52 typedef L<T> delay_result_type
|
Chris@102
|
53 typedef L<T> tail_result_type
|
Chris@102
|
54 template <class UU> struct cons_rebind {
|
Chris@102
|
55 typedef L<UU> type; // force type
|
Chris@102
|
56 typedef L<UU> delay_type; // delay type
|
Chris@102
|
57 };
|
Chris@102
|
58
|
Chris@102
|
59 L()
|
Chris@102
|
60 L( a_unique_type_for_nil )
|
Chris@102
|
61 template <class F> L(F) // F :: ()->L
|
Chris@102
|
62
|
Chris@102
|
63 constructor: force_result_type( T, L<T> )
|
Chris@102
|
64 template <class F>
|
Chris@102
|
65 constructor: force_result_type( T, F ) // F :: ()->L
|
Chris@102
|
66
|
Chris@102
|
67 template <class It>
|
Chris@102
|
68 L( It, It )
|
Chris@102
|
69
|
Chris@102
|
70 // FIX THIS instead of operator bool(), does Boost have something better?
|
Chris@102
|
71 operator bool() const
|
Chris@102
|
72 force_result_type force() const
|
Chris@102
|
73 delay_result_type delay() const
|
Chris@102
|
74 T head() const
|
Chris@102
|
75 tail_result_type tail() const
|
Chris@102
|
76
|
Chris@102
|
77 static const bool is_lazy; // true if can represent infinite lists
|
Chris@102
|
78
|
Chris@102
|
79 typedef const_iterator;
|
Chris@102
|
80 typedef const_iterator iterator; // ListLikes are immutable
|
Chris@102
|
81 iterator begin() const
|
Chris@102
|
82 iterator end() const
|
Chris@102
|
83 */
|
Chris@102
|
84
|
Chris@102
|
85 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
86 // End of section from Boost FC++ list.hpp
|
Chris@102
|
87 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
88
|
Chris@102
|
89 #ifndef BOOST_PHOENIX_FUNCTION_LAZY_LIST
|
Chris@102
|
90 #define BOOST_PHOENIX_FUNCTION_LAZY_LIST
|
Chris@102
|
91
|
Chris@102
|
92 #include <boost/phoenix/core.hpp>
|
Chris@102
|
93 #include <boost/phoenix/function.hpp>
|
Chris@102
|
94 #include <boost/intrusive_ptr.hpp>
|
Chris@102
|
95 #include <boost/function.hpp>
|
Chris@102
|
96 #include <boost/type_traits/type_with_alignment.hpp>
|
Chris@102
|
97 //#include "lazy_reuse.hpp"
|
Chris@102
|
98
|
Chris@102
|
99 namespace boost {
|
Chris@102
|
100
|
Chris@102
|
101 namespace phoenix {
|
Chris@102
|
102
|
Chris@102
|
103 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
104 // These are the list types being declared.
|
Chris@102
|
105 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
106
|
Chris@102
|
107 template <class T> class strict_list;
|
Chris@102
|
108 namespace impl {
|
Chris@102
|
109 template <class T> class list;
|
Chris@102
|
110 template <class T> class odd_list;
|
Chris@102
|
111 }
|
Chris@102
|
112 // in ref_count.hpp in BoostFC++ now in lazy_operator.hpp
|
Chris@102
|
113 //typedef unsigned int RefCountType;
|
Chris@102
|
114
|
Chris@102
|
115 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
116 // a_unique_type_for_nil moved to lazy_operator.hpp.
|
Chris@102
|
117 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
118
|
Chris@102
|
119
|
Chris@102
|
120 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
121 // Distinguish lazy lists (list and odd_list) from strict_list.
|
Chris@102
|
122 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
123
|
Chris@102
|
124 namespace lazy {
|
Chris@102
|
125 // Copied from Boost FC++ list.hpp
|
Chris@102
|
126 template <class L, bool is_lazy> struct ensure_lazy_helper {};
|
Chris@102
|
127 template <class L> struct ensure_lazy_helper<L,true> {
|
Chris@102
|
128 static void requires_lazy_list_to_prevent_infinite_recursion() {}
|
Chris@102
|
129 };
|
Chris@102
|
130 template <class L>
|
Chris@102
|
131 void ensure_lazy() {
|
Chris@102
|
132 ensure_lazy_helper<L,L::is_lazy>::
|
Chris@102
|
133 requires_lazy_list_to_prevent_infinite_recursion();
|
Chris@102
|
134 }
|
Chris@102
|
135
|
Chris@102
|
136 }
|
Chris@102
|
137
|
Chris@102
|
138 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
139 // Provide remove reference for types defined for list types.
|
Chris@102
|
140 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
141
|
Chris@102
|
142 namespace result_of {
|
Chris@102
|
143
|
Chris@102
|
144 template < typename L >
|
Chris@102
|
145 class ListType
|
Chris@102
|
146 {
|
Chris@102
|
147 public:
|
Chris@102
|
148 typedef typename boost::remove_reference<L>::type LType;
|
Chris@102
|
149 typedef typename LType::value_type value_type;
|
Chris@102
|
150 typedef typename LType::tail_result_type tail_result_type;
|
Chris@102
|
151 typedef typename LType::force_result_type force_result_type;
|
Chris@102
|
152 typedef typename LType::delay_result_type delay_result_type;
|
Chris@102
|
153 };
|
Chris@102
|
154
|
Chris@102
|
155 template <>
|
Chris@102
|
156 class ListType<a_unique_type_for_nil>
|
Chris@102
|
157 {
|
Chris@102
|
158 public:
|
Chris@102
|
159 typedef a_unique_type_for_nil LType;
|
Chris@102
|
160 //typedef a_unique_type_for_nil value_type;
|
Chris@102
|
161 };
|
Chris@102
|
162
|
Chris@102
|
163 template <typename F, typename T>
|
Chris@102
|
164 struct ResultType {
|
Chris@102
|
165 typedef typename impl::odd_list<T> type;
|
Chris@102
|
166 };
|
Chris@102
|
167
|
Chris@102
|
168 }
|
Chris@102
|
169
|
Chris@102
|
170 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
171 // ListLike is a property inherited by any list type to enable it to
|
Chris@102
|
172 // work with the functions being implemented in this file.
|
Chris@102
|
173 // It provides the check for the structure described above.
|
Chris@102
|
174 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
175
|
Chris@102
|
176 namespace listlike {
|
Chris@102
|
177
|
Chris@102
|
178 struct ListLike {}; // This lets us use is_base_and_derived() to see
|
Chris@102
|
179 // (at compile-time) what classes are user-defined lists.
|
Chris@102
|
180
|
Chris@102
|
181
|
Chris@102
|
182 template <class L, bool is_lazy> struct ensure_lazy_helper {};
|
Chris@102
|
183 template <class L> struct ensure_lazy_helper<L,true> {
|
Chris@102
|
184 static void requires_lazy_list_to_prevent_infinite_recursion() {}
|
Chris@102
|
185 };
|
Chris@102
|
186 template <class L>
|
Chris@102
|
187 void ensure_lazy() {
|
Chris@102
|
188 ensure_lazy_helper<L,L::is_lazy>::
|
Chris@102
|
189 requires_lazy_list_to_prevent_infinite_recursion();
|
Chris@102
|
190 }
|
Chris@102
|
191
|
Chris@102
|
192 template <class L, bool b>
|
Chris@102
|
193 struct EnsureListLikeHelp {
|
Chris@102
|
194 static void trying_to_call_a_list_function_on_a_non_list() {}
|
Chris@102
|
195 };
|
Chris@102
|
196 template <class L> struct EnsureListLikeHelp<L,false> { };
|
Chris@102
|
197 template <class L>
|
Chris@102
|
198 void EnsureListLike() {
|
Chris@102
|
199 typedef typename result_of::ListType<L>::LType LType;
|
Chris@102
|
200 EnsureListLikeHelp<L,boost::is_base_and_derived<ListLike,LType>::value>::
|
Chris@102
|
201 trying_to_call_a_list_function_on_a_non_list();
|
Chris@102
|
202 }
|
Chris@102
|
203
|
Chris@102
|
204 template <class L>
|
Chris@102
|
205 bool is_a_unique_type_for_nil(const L& l) {
|
Chris@102
|
206 return false;
|
Chris@102
|
207 }
|
Chris@102
|
208
|
Chris@102
|
209 template <>
|
Chris@102
|
210 bool is_a_unique_type_for_nil<a_unique_type_for_nil>
|
Chris@102
|
211 (const a_unique_type_for_nil& /* n */) {
|
Chris@102
|
212 return true;
|
Chris@102
|
213 }
|
Chris@102
|
214
|
Chris@102
|
215 template <class L>
|
Chris@102
|
216 struct detect_nil {
|
Chris@102
|
217 static const bool is_nil = false;
|
Chris@102
|
218 };
|
Chris@102
|
219
|
Chris@102
|
220 template <>
|
Chris@102
|
221 struct detect_nil<a_unique_type_for_nil> {
|
Chris@102
|
222 static const bool is_nil = true;
|
Chris@102
|
223 };
|
Chris@102
|
224
|
Chris@102
|
225 template <>
|
Chris@102
|
226 struct detect_nil<a_unique_type_for_nil&> {
|
Chris@102
|
227 static const bool is_nil = true;
|
Chris@102
|
228 };
|
Chris@102
|
229
|
Chris@102
|
230 template <>
|
Chris@102
|
231 struct detect_nil<const a_unique_type_for_nil&> {
|
Chris@102
|
232 static const bool is_nil = true;
|
Chris@102
|
233 };
|
Chris@102
|
234
|
Chris@102
|
235 }
|
Chris@102
|
236
|
Chris@102
|
237 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
238 // Implement lazy functions for list types. cat and cons come later.
|
Chris@102
|
239 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
240
|
Chris@102
|
241 #ifndef BOOST_PHOENIX_FUNCTION_MAX_LAZY_LIST_LENGTH
|
Chris@102
|
242 #define BOOST_PHOENIX_FUNCTION_MAX_LAZY_LIST_LENGTH 1000
|
Chris@102
|
243 #endif
|
Chris@102
|
244
|
Chris@102
|
245 namespace impl {
|
Chris@102
|
246
|
Chris@102
|
247 struct Head
|
Chris@102
|
248 {
|
Chris@102
|
249 template <typename Sig>
|
Chris@102
|
250 struct result;
|
Chris@102
|
251
|
Chris@102
|
252 template <typename This, typename L>
|
Chris@102
|
253 struct result<This(L)>
|
Chris@102
|
254 {
|
Chris@102
|
255 typedef typename result_of::ListType<L>::value_type type;
|
Chris@102
|
256 };
|
Chris@102
|
257
|
Chris@102
|
258 template <typename L>
|
Chris@102
|
259 typename result<Head(L)>::type
|
Chris@102
|
260 operator()(const L & l) const
|
Chris@102
|
261 {
|
Chris@102
|
262 listlike::EnsureListLike<L>();
|
Chris@102
|
263 return l.head();
|
Chris@102
|
264 }
|
Chris@102
|
265
|
Chris@102
|
266 };
|
Chris@102
|
267
|
Chris@102
|
268 struct Tail
|
Chris@102
|
269 {
|
Chris@102
|
270 template <typename Sig>
|
Chris@102
|
271 struct result;
|
Chris@102
|
272
|
Chris@102
|
273 template <typename This, typename L>
|
Chris@102
|
274 struct result<This(L)>
|
Chris@102
|
275 {
|
Chris@102
|
276 typedef typename result_of::ListType<L>::tail_result_type type;
|
Chris@102
|
277 };
|
Chris@102
|
278
|
Chris@102
|
279 template <typename L>
|
Chris@102
|
280 typename result<Tail(L)>::type
|
Chris@102
|
281 operator()(const L & l) const
|
Chris@102
|
282 {
|
Chris@102
|
283 listlike::EnsureListLike<L>();
|
Chris@102
|
284 return l.tail();
|
Chris@102
|
285 }
|
Chris@102
|
286
|
Chris@102
|
287 };
|
Chris@102
|
288
|
Chris@102
|
289 struct Null
|
Chris@102
|
290 {
|
Chris@102
|
291 template <typename Sig>
|
Chris@102
|
292 struct result;
|
Chris@102
|
293
|
Chris@102
|
294 template <typename This, typename L>
|
Chris@102
|
295 struct result<This(L)>
|
Chris@102
|
296 {
|
Chris@102
|
297 typedef bool type;
|
Chris@102
|
298 };
|
Chris@102
|
299
|
Chris@102
|
300 template <typename L>
|
Chris@102
|
301 typename result<Null(L)>::type
|
Chris@102
|
302 //bool
|
Chris@102
|
303 operator()(const L& l) const
|
Chris@102
|
304 {
|
Chris@102
|
305 listlike::EnsureListLike<L>();
|
Chris@102
|
306 return !l;
|
Chris@102
|
307 }
|
Chris@102
|
308
|
Chris@102
|
309 };
|
Chris@102
|
310
|
Chris@102
|
311 struct Delay {
|
Chris@102
|
312 template <typename Sig>
|
Chris@102
|
313 struct result;
|
Chris@102
|
314
|
Chris@102
|
315 template <typename This, typename L>
|
Chris@102
|
316 struct result<This(L)>
|
Chris@102
|
317 {
|
Chris@102
|
318 typedef typename result_of::ListType<L>::delay_result_type type;
|
Chris@102
|
319 };
|
Chris@102
|
320
|
Chris@102
|
321 template <typename L>
|
Chris@102
|
322 typename result<Delay(L)>::type
|
Chris@102
|
323 operator()(const L & l) const
|
Chris@102
|
324 {
|
Chris@102
|
325 listlike::EnsureListLike<L>();
|
Chris@102
|
326 return l.delay();
|
Chris@102
|
327 }
|
Chris@102
|
328
|
Chris@102
|
329 };
|
Chris@102
|
330
|
Chris@102
|
331 struct Force {
|
Chris@102
|
332 template <typename Sig>
|
Chris@102
|
333 struct result;
|
Chris@102
|
334
|
Chris@102
|
335 template <typename This, typename L>
|
Chris@102
|
336 struct result<This(L)>
|
Chris@102
|
337 {
|
Chris@102
|
338 typedef typename result_of::ListType<L>::force_result_type type;
|
Chris@102
|
339 };
|
Chris@102
|
340
|
Chris@102
|
341 template <typename L>
|
Chris@102
|
342 typename result<Force(L)>::type
|
Chris@102
|
343 operator()(const L & l) const
|
Chris@102
|
344 {
|
Chris@102
|
345 listlike::EnsureListLike<L>();
|
Chris@102
|
346 return l.force();
|
Chris@102
|
347 }
|
Chris@102
|
348
|
Chris@102
|
349 };
|
Chris@102
|
350
|
Chris@102
|
351 }
|
Chris@102
|
352 //BOOST_PHOENIX_ADAPT_CALLABLE(head, impl::head, 1)
|
Chris@102
|
353 //BOOST_PHOENIX_ADAPT_CALLABLE(tail, impl::tail, 1)
|
Chris@102
|
354 //BOOST_PHOENIX_ADAPT_CALLABLE(null, impl::null, 1)
|
Chris@102
|
355 typedef boost::phoenix::function<impl::Head> Head;
|
Chris@102
|
356 typedef boost::phoenix::function<impl::Tail> Tail;
|
Chris@102
|
357 typedef boost::phoenix::function<impl::Null> Null;
|
Chris@102
|
358 typedef boost::phoenix::function<impl::Delay> Delay;
|
Chris@102
|
359 typedef boost::phoenix::function<impl::Force> Force;
|
Chris@102
|
360 Head head;
|
Chris@102
|
361 Tail tail;
|
Chris@102
|
362 Null null;
|
Chris@102
|
363 Delay delay;
|
Chris@102
|
364 Force force;
|
Chris@102
|
365
|
Chris@102
|
366 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
367 // These definitions used for strict_list are imported from BoostFC++
|
Chris@102
|
368 // unchanged.
|
Chris@102
|
369 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
370
|
Chris@102
|
371 namespace impl {
|
Chris@102
|
372 template <class T>
|
Chris@102
|
373 struct strict_cons : public boost::noncopyable {
|
Chris@102
|
374 mutable RefCountType refC;
|
Chris@102
|
375 T head;
|
Chris@102
|
376 typedef boost::intrusive_ptr<strict_cons> tail_type;
|
Chris@102
|
377 tail_type tail;
|
Chris@102
|
378 strict_cons( const T& h, const tail_type& t ) : refC(0), head(h), tail(t) {}
|
Chris@102
|
379
|
Chris@102
|
380 };
|
Chris@102
|
381 template <class T>
|
Chris@102
|
382 void intrusive_ptr_add_ref( const strict_cons<T>* p ) {
|
Chris@102
|
383 ++ (p->refC);
|
Chris@102
|
384 }
|
Chris@102
|
385 template <class T>
|
Chris@102
|
386 void intrusive_ptr_release( const strict_cons<T>* p ) {
|
Chris@102
|
387 if( !--(p->refC) ) delete p;
|
Chris@102
|
388 }
|
Chris@102
|
389
|
Chris@102
|
390 template <class T>
|
Chris@102
|
391 class strict_list_iterator
|
Chris@102
|
392 : public std::iterator<std::input_iterator_tag,T,ptrdiff_t> {
|
Chris@102
|
393 typedef boost::intrusive_ptr<strict_cons<T> > rep_type;
|
Chris@102
|
394 rep_type l;
|
Chris@102
|
395 bool is_nil;
|
Chris@102
|
396 void advance() {
|
Chris@102
|
397 l = l->tail;
|
Chris@102
|
398 if( !l )
|
Chris@102
|
399 is_nil = true;
|
Chris@102
|
400 }
|
Chris@102
|
401 class Proxy { // needed for operator->
|
Chris@102
|
402 const T x;
|
Chris@102
|
403 friend class strict_list_iterator;
|
Chris@102
|
404 Proxy( const T& xx ) : x(xx) {}
|
Chris@102
|
405 public:
|
Chris@102
|
406 const T* operator->() const { return &x; }
|
Chris@102
|
407 };
|
Chris@102
|
408 public:
|
Chris@102
|
409 strict_list_iterator() : l(), is_nil(true) {}
|
Chris@102
|
410 explicit strict_list_iterator( const rep_type& ll ) : l(ll), is_nil(!ll) {}
|
Chris@102
|
411
|
Chris@102
|
412 const T operator*() const { return l->head; }
|
Chris@102
|
413 const Proxy operator->() const { return Proxy(l->head); }
|
Chris@102
|
414 strict_list_iterator<T>& operator++() {
|
Chris@102
|
415 advance();
|
Chris@102
|
416 return *this;
|
Chris@102
|
417 }
|
Chris@102
|
418 const strict_list_iterator<T> operator++(int) {
|
Chris@102
|
419 strict_list_iterator<T> i( *this );
|
Chris@102
|
420 advance();
|
Chris@102
|
421 return i;
|
Chris@102
|
422 }
|
Chris@102
|
423 bool operator==( const strict_list_iterator<T>& i ) const {
|
Chris@102
|
424 return is_nil && i.is_nil;
|
Chris@102
|
425 }
|
Chris@102
|
426 bool operator!=( const strict_list_iterator<T>& i ) const {
|
Chris@102
|
427 return ! this->operator==(i);
|
Chris@102
|
428 }
|
Chris@102
|
429 };
|
Chris@102
|
430 }
|
Chris@102
|
431
|
Chris@102
|
432 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
433 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
434
|
Chris@102
|
435 template <class T>
|
Chris@102
|
436 class strict_list : public listlike::ListLike
|
Chris@102
|
437 {
|
Chris@102
|
438 typedef boost::intrusive_ptr<impl::strict_cons<T> > rep_type;
|
Chris@102
|
439 rep_type rep;
|
Chris@102
|
440 struct Make {};
|
Chris@102
|
441
|
Chris@102
|
442 template <class Iter>
|
Chris@102
|
443 static rep_type help( Iter a, const Iter& b ) {
|
Chris@102
|
444 rep_type r;
|
Chris@102
|
445 while( a != b ) {
|
Chris@102
|
446 T x( *a );
|
Chris@102
|
447 r = rep_type( new impl::strict_cons<T>( x, r ) );
|
Chris@102
|
448 ++a;
|
Chris@102
|
449 }
|
Chris@102
|
450 return r;
|
Chris@102
|
451 }
|
Chris@102
|
452
|
Chris@102
|
453 public:
|
Chris@102
|
454 static const bool is_lazy = false;
|
Chris@102
|
455
|
Chris@102
|
456 typedef T value_type;
|
Chris@102
|
457 typedef strict_list force_result_type;
|
Chris@102
|
458 typedef strict_list delay_result_type;
|
Chris@102
|
459 typedef strict_list tail_result_type;
|
Chris@102
|
460 template <class UU> struct cons_rebind {
|
Chris@102
|
461 typedef strict_list<UU> type;
|
Chris@102
|
462 typedef strict_list<UU> delay_type;
|
Chris@102
|
463 };
|
Chris@102
|
464
|
Chris@102
|
465
|
Chris@102
|
466 strict_list( Make, const rep_type& r ) : rep(r) {}
|
Chris@102
|
467
|
Chris@102
|
468 strict_list() : rep() {}
|
Chris@102
|
469
|
Chris@102
|
470 strict_list( a_unique_type_for_nil ) : rep() {}
|
Chris@102
|
471
|
Chris@102
|
472 template <class F>
|
Chris@102
|
473 strict_list( const F& f ) : rep( f().rep ) {
|
Chris@102
|
474 // I cannot do this yet.
|
Chris@102
|
475 //functoid_traits<F>::template ensure_accepts<0>::args();
|
Chris@102
|
476 }
|
Chris@102
|
477
|
Chris@102
|
478 strict_list( const T& x, const strict_list& y )
|
Chris@102
|
479 : rep( new impl::strict_cons<T>(x,y.rep) ) {}
|
Chris@102
|
480
|
Chris@102
|
481 template <class F>
|
Chris@102
|
482 strict_list( const T& x, const F& f )
|
Chris@102
|
483 : rep( new impl::strict_cons<T>(x,f().rep) ) {}
|
Chris@102
|
484
|
Chris@102
|
485 operator bool() const { return (bool)rep; }
|
Chris@102
|
486 force_result_type force() const { return *this; }
|
Chris@102
|
487 delay_result_type delay() const { return *this; }
|
Chris@102
|
488 T head() const {
|
Chris@102
|
489 #ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
|
Chris@102
|
490 if( !*this )
|
Chris@102
|
491 throw lazy_exception("Tried to take head() of empty strict_list");
|
Chris@102
|
492 #endif
|
Chris@102
|
493 return rep->head;
|
Chris@102
|
494 }
|
Chris@102
|
495 tail_result_type tail() const {
|
Chris@102
|
496 #ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
|
Chris@102
|
497 if( !*this )
|
Chris@102
|
498 throw lazy_exception("Tried to take tail() of empty strict_list");
|
Chris@102
|
499 #endif
|
Chris@102
|
500 return strict_list(Make(),rep->tail);
|
Chris@102
|
501 }
|
Chris@102
|
502
|
Chris@102
|
503 template <class Iter>
|
Chris@102
|
504 strict_list( const Iter& a, const Iter& b ) : rep( rep_type() ) {
|
Chris@102
|
505 // How ironic. We need to reverse the iterator range in order to
|
Chris@102
|
506 // non-recursively build this!
|
Chris@102
|
507 std::vector<T> tmp(a,b);
|
Chris@102
|
508 rep = help( tmp.rbegin(), tmp.rend() );
|
Chris@102
|
509 }
|
Chris@102
|
510
|
Chris@102
|
511 // Since the strict_cons destructor can't call the strict_list
|
Chris@102
|
512 // destructor, the "simple" iterative destructor is correct and
|
Chris@102
|
513 // efficient. Hurray.
|
Chris@102
|
514 ~strict_list() { while(rep && (rep->refC == 1)) rep = rep->tail; }
|
Chris@102
|
515
|
Chris@102
|
516 // The following helps makes strict_list almost an STL "container"
|
Chris@102
|
517 typedef impl::strict_list_iterator<T> const_iterator;
|
Chris@102
|
518 typedef const_iterator iterator; // strict_list is immutable
|
Chris@102
|
519 iterator begin() const { return impl::strict_list_iterator<T>( rep ); }
|
Chris@102
|
520 iterator end() const { return impl::strict_list_iterator<T>(); }
|
Chris@102
|
521
|
Chris@102
|
522 };
|
Chris@102
|
523
|
Chris@102
|
524 // All of these null head and tail are now non lazy using e.g. null(a)().
|
Chris@102
|
525 // They need an extra () e.g. null(a)().
|
Chris@102
|
526 template <class T>
|
Chris@102
|
527 bool operator==( const strict_list<T>& a, a_unique_type_for_nil ) {
|
Chris@102
|
528 return null(a)();
|
Chris@102
|
529 }
|
Chris@102
|
530 template <class T>
|
Chris@102
|
531 bool operator==( a_unique_type_for_nil, const strict_list<T>& a ) {
|
Chris@102
|
532 return null(a)();
|
Chris@102
|
533 }
|
Chris@102
|
534 template <class T>
|
Chris@102
|
535 bool operator==( const strict_list<T>& a, const strict_list<T>& b ) {
|
Chris@102
|
536 if( null(a)() && null(b)() )
|
Chris@102
|
537 return true;
|
Chris@102
|
538 if( null(a)() || null(b)() )
|
Chris@102
|
539 return false;
|
Chris@102
|
540 return (head(a)()==head(b)()) &&
|
Chris@102
|
541 (tail(a)()==tail(b)());
|
Chris@102
|
542 }
|
Chris@102
|
543
|
Chris@102
|
544 template <class T>
|
Chris@102
|
545 bool operator<( const strict_list<T>& a, const strict_list<T>& b ) {
|
Chris@102
|
546 if( null(a)() && !null(b)() ) return true;
|
Chris@102
|
547 if( null(b)() ) return false;
|
Chris@102
|
548 if( head(b)() < head(a)() ) return false;
|
Chris@102
|
549 if( head(a)() < head(b)() ) return true;
|
Chris@102
|
550 return (tail(a)() < tail(b)());
|
Chris@102
|
551 }
|
Chris@102
|
552 template <class T>
|
Chris@102
|
553 bool operator<( const strict_list<T>&, a_unique_type_for_nil ) {
|
Chris@102
|
554 return false;
|
Chris@102
|
555 }
|
Chris@102
|
556 template <class T>
|
Chris@102
|
557 bool operator<( a_unique_type_for_nil, const strict_list<T>& b ) {
|
Chris@102
|
558 return !(null(b)());
|
Chris@102
|
559 }
|
Chris@102
|
560
|
Chris@102
|
561 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
562 // Class list<T> is the primary interface to the user for lazy lists.
|
Chris@102
|
563 //////////////////////////////////////////////////////////////////////{
|
Chris@102
|
564 namespace impl {
|
Chris@102
|
565 using fcpp::INV;
|
Chris@102
|
566 using fcpp::VAR;
|
Chris@102
|
567 using fcpp::reuser2;
|
Chris@102
|
568
|
Chris@102
|
569 struct CacheEmpty {};
|
Chris@102
|
570
|
Chris@102
|
571 template <class T> class Cache;
|
Chris@102
|
572 template <class T> class odd_list;
|
Chris@102
|
573 template <class T> class list_iterator;
|
Chris@102
|
574 template <class It, class T>
|
Chris@102
|
575 struct ListItHelp2 /*: public c_fun_type<It,It,odd_list<T> >*/ {
|
Chris@102
|
576 // This will need a return type.
|
Chris@102
|
577 typedef odd_list<T> return_type;
|
Chris@102
|
578 odd_list<T> operator()( It begin, const It& end,
|
Chris@102
|
579 reuser2<INV,VAR,INV,ListItHelp2<It,T>,It,It> r = NIL ) const;
|
Chris@102
|
580 };
|
Chris@102
|
581 template <class U,class F> struct cvt;
|
Chris@102
|
582 template <class T, class F, class R> struct ListHelp;
|
Chris@102
|
583 template <class T> Cache<T>* xempty_helper();
|
Chris@102
|
584 template <class T, class F, class L, bool b> struct ConsHelp2;
|
Chris@102
|
585
|
Chris@102
|
586 struct ListRaw {};
|
Chris@102
|
587
|
Chris@102
|
588 template <class T>
|
Chris@102
|
589 class list : public listlike::ListLike
|
Chris@102
|
590 {
|
Chris@102
|
591 // never NIL, unless an empty odd_list
|
Chris@102
|
592 boost::intrusive_ptr<Cache<T> > rep;
|
Chris@102
|
593
|
Chris@102
|
594 template <class U> friend class Cache;
|
Chris@102
|
595 template <class U> friend class odd_list;
|
Chris@102
|
596 template <class TT, class F, class L, bool b> friend struct ConsHelp2;
|
Chris@102
|
597 template <class U,class F> friend struct cvt;
|
Chris@102
|
598
|
Chris@102
|
599 list( const boost::intrusive_ptr<Cache<T> >& p ) : rep(p) { }
|
Chris@102
|
600 list( ListRaw, Cache<T>* p ) : rep(p) { }
|
Chris@102
|
601
|
Chris@102
|
602 bool priv_isEmpty() const {
|
Chris@102
|
603 return rep->cache().second.rep == Cache<T>::XNIL();
|
Chris@102
|
604 }
|
Chris@102
|
605 T priv_head() const {
|
Chris@102
|
606 #ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
|
Chris@102
|
607 if( priv_isEmpty() )
|
Chris@102
|
608 throw lazy_exception("Tried to take head() of empty list");
|
Chris@102
|
609 #endif
|
Chris@102
|
610 return rep->cache().first();
|
Chris@102
|
611 }
|
Chris@102
|
612 list<T> priv_tail() const {
|
Chris@102
|
613 #ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
|
Chris@102
|
614 if( priv_isEmpty() )
|
Chris@102
|
615 throw lazy_exception("Tried to take tail() of empty list");
|
Chris@102
|
616 #endif
|
Chris@102
|
617 return rep->cache().second;
|
Chris@102
|
618 }
|
Chris@102
|
619
|
Chris@102
|
620
|
Chris@102
|
621 public:
|
Chris@102
|
622 static const bool is_lazy = true;
|
Chris@102
|
623
|
Chris@102
|
624 typedef T value_type;
|
Chris@102
|
625 typedef list tail_result_type;
|
Chris@102
|
626 typedef odd_list<T> force_result_type;
|
Chris@102
|
627 typedef list delay_result_type;
|
Chris@102
|
628 template <class UU> struct cons_rebind {
|
Chris@102
|
629 typedef odd_list<UU> type;
|
Chris@102
|
630 typedef list<UU> delay_type;
|
Chris@102
|
631 };
|
Chris@102
|
632
|
Chris@102
|
633 list( a_unique_type_for_nil ) : rep( Cache<T>::XEMPTY() ) { }
|
Chris@102
|
634 list() : rep( Cache<T>::XEMPTY() ) { }
|
Chris@102
|
635
|
Chris@102
|
636 template <class F> // works on both ()->odd_list and ()->list
|
Chris@102
|
637 // At the moment this is fixed for odd_list<T>.
|
Chris@102
|
638 // I need to do more work to get the general result.
|
Chris@102
|
639 list( const F& f )
|
Chris@102
|
640 : rep( ListHelp<T,F,odd_list<T> >()(f) ) { }
|
Chris@102
|
641 //: rep( ListHelp<T,F,typename F::result_type>()(f) ) { }
|
Chris@102
|
642
|
Chris@102
|
643 operator bool() const { return !priv_isEmpty(); }
|
Chris@102
|
644 const force_result_type& force() const { return rep->cache(); }
|
Chris@102
|
645 const delay_result_type& delay() const { return *this; }
|
Chris@102
|
646 // Note: force returns a reference;
|
Chris@102
|
647 // implicit conversion now returns a copy.
|
Chris@102
|
648 operator odd_list<T>() const { return force(); }
|
Chris@102
|
649
|
Chris@102
|
650 T head() const { return priv_head(); }
|
Chris@102
|
651 tail_result_type tail() const { return priv_tail(); }
|
Chris@102
|
652
|
Chris@102
|
653 // The following helps makes list almost an STL "container"
|
Chris@102
|
654 typedef list_iterator<T> const_iterator;
|
Chris@102
|
655 typedef const_iterator iterator; // list is immutable
|
Chris@102
|
656 iterator begin() const { return list_iterator<T>( *this ); }
|
Chris@102
|
657 iterator end() const { return list_iterator<T>(); }
|
Chris@102
|
658
|
Chris@102
|
659 // end of list<T>
|
Chris@102
|
660 };
|
Chris@102
|
661
|
Chris@102
|
662 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
663 // Class odd_list<T> is not normally accessed by the user.
|
Chris@102
|
664 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
665
|
Chris@102
|
666 struct OddListDummyY {};
|
Chris@102
|
667
|
Chris@102
|
668 template <class T>
|
Chris@102
|
669 class odd_list : public listlike::ListLike
|
Chris@102
|
670 {
|
Chris@102
|
671 public:
|
Chris@102
|
672 typedef
|
Chris@102
|
673 typename boost::type_with_alignment<boost::alignment_of<T>::value>::type
|
Chris@102
|
674 xfst_type;
|
Chris@102
|
675 private:
|
Chris@102
|
676 union { xfst_type fst; unsigned char dummy[sizeof(T)]; };
|
Chris@102
|
677
|
Chris@102
|
678 const T& first() const {
|
Chris@102
|
679 return *static_cast<const T*>(static_cast<const void*>(&fst));
|
Chris@102
|
680 }
|
Chris@102
|
681 T& first() {
|
Chris@102
|
682 return *static_cast<T*>(static_cast<void*>(&fst));
|
Chris@102
|
683 }
|
Chris@102
|
684 list<T> second; // If XNIL, then this odd_list is NIL
|
Chris@102
|
685
|
Chris@102
|
686 template <class U> friend class list;
|
Chris@102
|
687 template <class U> friend class Cache;
|
Chris@102
|
688
|
Chris@102
|
689 odd_list( OddListDummyY )
|
Chris@102
|
690 : second( Cache<T>::XBAD() ) { }
|
Chris@102
|
691
|
Chris@102
|
692 void init( const T& x ) {
|
Chris@102
|
693 new (static_cast<void*>(&fst)) T(x);
|
Chris@102
|
694 }
|
Chris@102
|
695
|
Chris@102
|
696 bool fst_is_valid() const {
|
Chris@102
|
697 if( second.rep != Cache<T>::XNIL() )
|
Chris@102
|
698 if( second.rep != Cache<T>::XBAD() )
|
Chris@102
|
699 return true;
|
Chris@102
|
700 return false;
|
Chris@102
|
701 }
|
Chris@102
|
702
|
Chris@102
|
703 bool priv_isEmpty() const { return second.rep == Cache<T>::XNIL(); }
|
Chris@102
|
704 T priv_head() const {
|
Chris@102
|
705 #ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
|
Chris@102
|
706 if( priv_isEmpty() )
|
Chris@102
|
707 throw lazy_exception("Tried to take head() of empty odd_list");
|
Chris@102
|
708 #endif
|
Chris@102
|
709 return first();
|
Chris@102
|
710 }
|
Chris@102
|
711
|
Chris@102
|
712 list<T> priv_tail() const {
|
Chris@102
|
713 #ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
|
Chris@102
|
714 if( priv_isEmpty() )
|
Chris@102
|
715 throw lazy_exception("Tried to take tail() of empty odd_list");
|
Chris@102
|
716 #endif
|
Chris@102
|
717 return second;
|
Chris@102
|
718 }
|
Chris@102
|
719
|
Chris@102
|
720 public:
|
Chris@102
|
721 static const bool is_lazy = true;
|
Chris@102
|
722
|
Chris@102
|
723 typedef T value_type;
|
Chris@102
|
724 typedef list<T> tail_result_type;
|
Chris@102
|
725 typedef odd_list<T> force_result_type;
|
Chris@102
|
726 typedef list<T> delay_result_type;
|
Chris@102
|
727 template <class UU> struct cons_rebind {
|
Chris@102
|
728 typedef odd_list<UU> type;
|
Chris@102
|
729 typedef list<UU> delay_type;
|
Chris@102
|
730 };
|
Chris@102
|
731
|
Chris@102
|
732 odd_list() : second( Cache<T>::XNIL() ) { }
|
Chris@102
|
733 odd_list( a_unique_type_for_nil ) : second( Cache<T>::XNIL() ) { }
|
Chris@102
|
734 odd_list( const T& x, const list<T>& y ) : second(y) { init(x); }
|
Chris@102
|
735 odd_list( const T& x, a_unique_type_for_nil ) : second(NIL) { init(x); }
|
Chris@102
|
736
|
Chris@102
|
737 odd_list( const odd_list<T>& x ) : second(x.second) {
|
Chris@102
|
738 if( fst_is_valid() ) {
|
Chris@102
|
739 init( x.first() );
|
Chris@102
|
740 }
|
Chris@102
|
741 }
|
Chris@102
|
742
|
Chris@102
|
743 template <class It>
|
Chris@102
|
744 odd_list( It begin, const It& end )
|
Chris@102
|
745 : second( begin==end ? Cache<T>::XNIL() :
|
Chris@102
|
746 ( init(*begin++), list<T>( begin, end ) ) ) {}
|
Chris@102
|
747
|
Chris@102
|
748 odd_list<T>& operator=( const odd_list<T>& x ) {
|
Chris@102
|
749 if( this == &x ) return *this;
|
Chris@102
|
750 if( fst_is_valid() ) {
|
Chris@102
|
751 if( x.fst_is_valid() )
|
Chris@102
|
752 first() = x.first();
|
Chris@102
|
753 else
|
Chris@102
|
754 first().~T();
|
Chris@102
|
755 }
|
Chris@102
|
756 else {
|
Chris@102
|
757 if( x.fst_is_valid() )
|
Chris@102
|
758 init( x.first() );
|
Chris@102
|
759 }
|
Chris@102
|
760 second = x.second;
|
Chris@102
|
761 return *this;
|
Chris@102
|
762 }
|
Chris@102
|
763
|
Chris@102
|
764 ~odd_list() {
|
Chris@102
|
765 if( fst_is_valid() ) {
|
Chris@102
|
766 first().~T();
|
Chris@102
|
767 }
|
Chris@102
|
768 }
|
Chris@102
|
769
|
Chris@102
|
770 operator bool() const { return !priv_isEmpty(); }
|
Chris@102
|
771 const force_result_type& force() const { return *this; }
|
Chris@102
|
772 delay_result_type delay() const { return list<T>(*this); }
|
Chris@102
|
773
|
Chris@102
|
774 T head() const { return priv_head(); }
|
Chris@102
|
775 tail_result_type tail() const { return priv_tail(); }
|
Chris@102
|
776
|
Chris@102
|
777 // The following helps makes odd_list almost an STL "container"
|
Chris@102
|
778 typedef list_iterator<T> const_iterator;
|
Chris@102
|
779 typedef const_iterator iterator; // odd_list is immutable
|
Chris@102
|
780 iterator begin() const { return list_iterator<T>( this->delay() ); }
|
Chris@102
|
781 iterator end() const { return list_iterator<T>(); }
|
Chris@102
|
782
|
Chris@102
|
783 // end of odd_list<T>
|
Chris@102
|
784 };
|
Chris@102
|
785
|
Chris@102
|
786 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
787 // struct cvt
|
Chris@102
|
788 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
789
|
Chris@102
|
790 // This converts ()->list<T> to ()->odd_list<T>.
|
Chris@102
|
791 // In other words, here is the 'extra work' done when using the
|
Chris@102
|
792 // unoptimized interface.
|
Chris@102
|
793 template <class U,class F>
|
Chris@102
|
794 struct cvt /*: public c_fun_type<odd_list<U> >*/ {
|
Chris@102
|
795 typedef odd_list<U> return_type;
|
Chris@102
|
796 F f;
|
Chris@102
|
797 cvt( const F& ff ) : f(ff) {}
|
Chris@102
|
798 odd_list<U> operator()() const {
|
Chris@102
|
799 list<U> l = f();
|
Chris@102
|
800 return l.force();
|
Chris@102
|
801 }
|
Chris@102
|
802 };
|
Chris@102
|
803
|
Chris@102
|
804
|
Chris@102
|
805 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
806 // Cache<T> and associated functions.
|
Chris@102
|
807 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
808
|
Chris@102
|
809 // I malloc a RefCountType to hold the refCount and init it to 1 to ensure the
|
Chris@102
|
810 // refCount will never get to 0, so the destructor-of-global-object
|
Chris@102
|
811 // order at the end of the program is a non-issue. In other words, the
|
Chris@102
|
812 // memory allocated here is only reclaimed by the operating system.
|
Chris@102
|
813 template <class T>
|
Chris@102
|
814 Cache<T>* xnil_helper() {
|
Chris@102
|
815 void *p = std::malloc( sizeof(RefCountType) );
|
Chris@102
|
816 *((RefCountType*)p) = 1;
|
Chris@102
|
817 return static_cast<Cache<T>*>( p );
|
Chris@102
|
818 }
|
Chris@102
|
819
|
Chris@102
|
820 template <class T>
|
Chris@102
|
821 Cache<T>* xnil_helper_nil() {
|
Chris@102
|
822 Cache<T>* p = xnil_helper<T>();
|
Chris@102
|
823 return p;
|
Chris@102
|
824 }
|
Chris@102
|
825
|
Chris@102
|
826 template <class T>
|
Chris@102
|
827 Cache<T>* xnil_helper_bad() {
|
Chris@102
|
828 Cache<T>* p = xnil_helper<T>();
|
Chris@102
|
829 return p;
|
Chris@102
|
830 }
|
Chris@102
|
831
|
Chris@102
|
832 template <class T>
|
Chris@102
|
833 Cache<T>* xempty_helper() {
|
Chris@102
|
834 Cache<T>* p = new Cache<T>( CacheEmpty() );
|
Chris@102
|
835 return p;
|
Chris@102
|
836 }
|
Chris@102
|
837
|
Chris@102
|
838 // This makes a boost phoenix function type with return type
|
Chris@102
|
839 // odd_list<T>
|
Chris@102
|
840 template <class T>
|
Chris@102
|
841 struct fun0_type_helper{
|
Chris@102
|
842 typedef boost::function0<odd_list<T> > fun_type;
|
Chris@102
|
843 typedef boost::phoenix::function<fun_type> phx_type;
|
Chris@102
|
844 };
|
Chris@102
|
845
|
Chris@102
|
846
|
Chris@102
|
847 template <class T>
|
Chris@102
|
848 struct make_fun0_odd_list {
|
Chris@102
|
849
|
Chris@102
|
850 typedef typename fun0_type_helper<T>::fun_type fun_type;
|
Chris@102
|
851 typedef typename fun0_type_helper<T>::phx_type phx_type;
|
Chris@102
|
852 typedef phx_type result_type;
|
Chris@102
|
853
|
Chris@102
|
854 template <class F>
|
Chris@102
|
855 result_type operator()(const F& f) const
|
Chris@102
|
856 {
|
Chris@102
|
857 fun_type ff(f);
|
Chris@102
|
858 phx_type g(ff);
|
Chris@102
|
859 return g;
|
Chris@102
|
860 }
|
Chris@102
|
861
|
Chris@102
|
862 // Overload for the case where it is a boost phoenix function already.
|
Chris@102
|
863 template <class F>
|
Chris@102
|
864 typename boost::phoenix::function<F> operator()
|
Chris@102
|
865 (const boost::phoenix::function<F>& f) const
|
Chris@102
|
866 {
|
Chris@102
|
867 return f;
|
Chris@102
|
868 }
|
Chris@102
|
869
|
Chris@102
|
870 };
|
Chris@102
|
871
|
Chris@102
|
872 template <class T>
|
Chris@102
|
873 class Cache : boost::noncopyable {
|
Chris@102
|
874 mutable RefCountType refC;
|
Chris@102
|
875 // This is the boost::function type
|
Chris@102
|
876 typedef typename fun0_type_helper<T>::fun_type fun_odd_list_T;
|
Chris@102
|
877 // This is the boost::phoenix::function type;
|
Chris@102
|
878 typedef typename fun0_type_helper<T>::phx_type fun0_odd_list_T;
|
Chris@102
|
879 mutable fun0_odd_list_T fxn;
|
Chris@102
|
880 mutable odd_list<T> val;
|
Chris@102
|
881 // val.second.rep can be XBAD, XNIL, or a valid ptr
|
Chris@102
|
882 // - XBAD: val is invalid (fxn is valid)
|
Chris@102
|
883 // - XNIL: this is the empty list
|
Chris@102
|
884 // - anything else: val.first() is head, val.second is tail()
|
Chris@102
|
885
|
Chris@102
|
886 // This functoid should never be called; it represents a
|
Chris@102
|
887 // self-referent Cache, which should be impossible under the current
|
Chris@102
|
888 // implementation. Nonetheless, we need a 'dummy' function object to
|
Chris@102
|
889 // represent invalid 'fxn's (val.second.rep!=XBAD), and this
|
Chris@102
|
890 // implementation seems to be among the most reasonable.
|
Chris@102
|
891 struct blackhole_helper /*: c_fun_type< odd_list<T> >*/ {
|
Chris@102
|
892 typedef odd_list<T> return_type;
|
Chris@102
|
893 odd_list<T> operator()() const {
|
Chris@102
|
894 #ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
|
Chris@102
|
895 throw lazy_exception("You have entered a black hole.");
|
Chris@102
|
896 #else
|
Chris@102
|
897 return odd_list<T>();
|
Chris@102
|
898 #endif
|
Chris@102
|
899 }
|
Chris@102
|
900 };
|
Chris@102
|
901
|
Chris@102
|
902 // Don't get rid of these XFOO() functions; they impose no overhead,
|
Chris@102
|
903 // and provide a useful place to add debugging code for tracking down
|
Chris@102
|
904 // before-main()-order-of-initialization problems.
|
Chris@102
|
905 static const boost::intrusive_ptr<Cache<T> >& XEMPTY() {
|
Chris@102
|
906 static boost::intrusive_ptr<Cache<T> > xempty( xempty_helper<T>() );
|
Chris@102
|
907 return xempty;
|
Chris@102
|
908 }
|
Chris@102
|
909 static const boost::intrusive_ptr<Cache<T> >& XNIL() {
|
Chris@102
|
910 // this list is nil
|
Chris@102
|
911 static boost::intrusive_ptr<Cache<T> > xnil( xnil_helper_nil<T>() );
|
Chris@102
|
912 return xnil;
|
Chris@102
|
913 }
|
Chris@102
|
914
|
Chris@102
|
915 static const boost::intrusive_ptr<Cache<T> >& XBAD() {
|
Chris@102
|
916 // the pair is invalid; use fxn
|
Chris@102
|
917 static boost::intrusive_ptr<Cache<T> > xbad( xnil_helper_bad<T>() );
|
Chris@102
|
918 return xbad;
|
Chris@102
|
919 }
|
Chris@102
|
920
|
Chris@102
|
921 static fun0_odd_list_T /*<odd_list<T> >*/ the_blackhole;
|
Chris@102
|
922 static fun0_odd_list_T& blackhole() {
|
Chris@102
|
923 static fun0_odd_list_T the_blackhole;
|
Chris@102
|
924 //( make_fun0_odd_list<T>()( blackhole_helper() ) );
|
Chris@102
|
925 return the_blackhole;
|
Chris@102
|
926 }
|
Chris@102
|
927
|
Chris@102
|
928 odd_list<T>& cache() const {
|
Chris@102
|
929 if( val.second.rep == XBAD() ) {
|
Chris@102
|
930 val = fxn()();
|
Chris@102
|
931 fxn = blackhole();
|
Chris@102
|
932 }
|
Chris@102
|
933 return val;
|
Chris@102
|
934 }
|
Chris@102
|
935
|
Chris@102
|
936 template <class U> friend class list;
|
Chris@102
|
937 template <class U> friend class odd_list;
|
Chris@102
|
938 template <class TT, class F, class L, bool b> friend struct ConsHelp2;
|
Chris@102
|
939 template <class U,class F> friend struct cvt;
|
Chris@102
|
940 template <class U, class F, class R> friend struct ListHelp;
|
Chris@102
|
941 template <class U> friend Cache<U>* xempty_helper();
|
Chris@102
|
942
|
Chris@102
|
943 Cache( CacheEmpty ) : refC(0), fxn(blackhole()), val() {}
|
Chris@102
|
944 Cache( const odd_list<T>& x ) : refC(0), fxn(blackhole()), val(x) {}
|
Chris@102
|
945 Cache( const T& x, const list<T>& l ) : refC(0),fxn(blackhole()),val(x,l)
|
Chris@102
|
946 {}
|
Chris@102
|
947
|
Chris@102
|
948 Cache( const fun0_odd_list_T& f )
|
Chris@102
|
949 : refC(0), fxn(f), val( OddListDummyY() ) {}
|
Chris@102
|
950
|
Chris@102
|
951 // f must be a boost phoenix function object?
|
Chris@102
|
952 template <class F>
|
Chris@102
|
953 Cache( const F& f ) // ()->odd_list
|
Chris@102
|
954 : refC(0), fxn(make_fun0_odd_list<T>()(f)), val( OddListDummyY() ) {}
|
Chris@102
|
955
|
Chris@102
|
956 // This is for ()->list<T> to ()->odd_list<T>
|
Chris@102
|
957 struct CvtFxn {};
|
Chris@102
|
958 template <class F>
|
Chris@102
|
959 Cache( CvtFxn, const F& f ) // ()->list
|
Chris@102
|
960 : refC(0), fxn(make_fun0_odd_list<T>()(cvt<T,F>(f))), val( OddListDummyY() ) {}
|
Chris@102
|
961
|
Chris@102
|
962 template <class X>
|
Chris@102
|
963 friend void intrusive_ptr_add_ref( const Cache<X>* p );
|
Chris@102
|
964 template <class X>
|
Chris@102
|
965 friend void intrusive_ptr_release( const Cache<X>* p );
|
Chris@102
|
966 };
|
Chris@102
|
967
|
Chris@102
|
968 template <class T>
|
Chris@102
|
969 void intrusive_ptr_add_ref( const Cache<T>* p ) {
|
Chris@102
|
970 ++ (p->refC);
|
Chris@102
|
971 }
|
Chris@102
|
972 template <class T>
|
Chris@102
|
973 void intrusive_ptr_release( const Cache<T>* p ) {
|
Chris@102
|
974 if( !--(p->refC) ) delete p;
|
Chris@102
|
975 }
|
Chris@102
|
976
|
Chris@102
|
977 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
978 // Rest of list's stuff
|
Chris@102
|
979 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
980
|
Chris@102
|
981 template <class T, class F> struct ListHelp<T,F,list<T> > {
|
Chris@102
|
982 boost::intrusive_ptr<Cache<T> > operator()( const F& f ) const {
|
Chris@102
|
983 return boost::intrusive_ptr<Cache<T> >
|
Chris@102
|
984 (new Cache<T>(typename Cache<T>::CvtFxn(),f));
|
Chris@102
|
985 }
|
Chris@102
|
986 };
|
Chris@102
|
987 template <class T, class F> struct ListHelp<T,F,odd_list<T> > {
|
Chris@102
|
988 boost::intrusive_ptr<Cache<T> > operator()( const F& f ) const {
|
Chris@102
|
989 return boost::intrusive_ptr<Cache<T> >(new Cache<T>(f));
|
Chris@102
|
990 }
|
Chris@102
|
991 };
|
Chris@102
|
992
|
Chris@102
|
993 template <class T>
|
Chris@102
|
994 class list_iterator
|
Chris@102
|
995 : public std::iterator<std::input_iterator_tag,T,ptrdiff_t> {
|
Chris@102
|
996 list<T> l;
|
Chris@102
|
997 bool is_nil;
|
Chris@102
|
998 void advance() {
|
Chris@102
|
999 l = l.tail();
|
Chris@102
|
1000 if( !l )
|
Chris@102
|
1001 is_nil = true;
|
Chris@102
|
1002 }
|
Chris@102
|
1003 class Proxy { // needed for operator->
|
Chris@102
|
1004 const T x;
|
Chris@102
|
1005 friend class list_iterator;
|
Chris@102
|
1006 Proxy( const T& xx ) : x(xx) {}
|
Chris@102
|
1007 public:
|
Chris@102
|
1008 const T* operator->() const { return &x; }
|
Chris@102
|
1009 };
|
Chris@102
|
1010 public:
|
Chris@102
|
1011 list_iterator() : l(), is_nil(true) {}
|
Chris@102
|
1012 explicit list_iterator( const list<T>& ll ) : l(ll), is_nil(!ll) {}
|
Chris@102
|
1013
|
Chris@102
|
1014 const T operator*() const { return l.head(); }
|
Chris@102
|
1015 const Proxy operator->() const { return Proxy(l.head()); }
|
Chris@102
|
1016 list_iterator<T>& operator++() {
|
Chris@102
|
1017 advance();
|
Chris@102
|
1018 return *this;
|
Chris@102
|
1019 }
|
Chris@102
|
1020 const list_iterator<T> operator++(int) {
|
Chris@102
|
1021 list_iterator<T> i( *this );
|
Chris@102
|
1022 advance();
|
Chris@102
|
1023 return i;
|
Chris@102
|
1024 }
|
Chris@102
|
1025 bool operator==( const list_iterator<T>& i ) const {
|
Chris@102
|
1026 return is_nil && i.is_nil;
|
Chris@102
|
1027 }
|
Chris@102
|
1028 bool operator!=( const list_iterator<T>& i ) const {
|
Chris@102
|
1029 return ! this->operator==(i);
|
Chris@102
|
1030 }
|
Chris@102
|
1031 };
|
Chris@102
|
1032
|
Chris@102
|
1033
|
Chris@102
|
1034 } // namespace impl
|
Chris@102
|
1035
|
Chris@102
|
1036 using impl::list;
|
Chris@102
|
1037 using impl::odd_list;
|
Chris@102
|
1038 using impl::list_iterator;
|
Chris@102
|
1039
|
Chris@102
|
1040 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
1041 // op== and op<, overloaded for all combos of list, odd_list, and NIL
|
Chris@102
|
1042 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
1043 // All of these null head and tail are now non lazy using e.g. null(a)().
|
Chris@102
|
1044 // They need an extra () e.g. null(a)().
|
Chris@102
|
1045
|
Chris@102
|
1046 // FIX THIS comparison operators can be implemented simpler with enable_if
|
Chris@102
|
1047 template <class T>
|
Chris@102
|
1048 bool operator==( const odd_list<T>& a, a_unique_type_for_nil ) {
|
Chris@102
|
1049 return null(a)();
|
Chris@102
|
1050 }
|
Chris@102
|
1051 template <class T>
|
Chris@102
|
1052 bool operator==( const list<T>& a, a_unique_type_for_nil ) {
|
Chris@102
|
1053 return null(a)();
|
Chris@102
|
1054 }
|
Chris@102
|
1055 template <class T>
|
Chris@102
|
1056 bool operator==( a_unique_type_for_nil, const odd_list<T>& a ) {
|
Chris@102
|
1057 return null(a)();
|
Chris@102
|
1058 }
|
Chris@102
|
1059 template <class T>
|
Chris@102
|
1060 bool operator==( a_unique_type_for_nil, const list<T>& a ) {
|
Chris@102
|
1061 return null(a)();
|
Chris@102
|
1062 }
|
Chris@102
|
1063 template <class T>
|
Chris@102
|
1064 bool operator==( const list<T>& a, const list<T>& b ) {
|
Chris@102
|
1065 if( null(a)() && null(b)() )
|
Chris@102
|
1066 return true;
|
Chris@102
|
1067 if( null(a)() || null(b)() )
|
Chris@102
|
1068 return false;
|
Chris@102
|
1069 return (head(a)()==head(b)()) && (tail(a)()==tail(b)());
|
Chris@102
|
1070 }
|
Chris@102
|
1071 template <class T>
|
Chris@102
|
1072 bool operator==( const odd_list<T>& a, const odd_list<T>& b ) {
|
Chris@102
|
1073 if( null(a)() && null(b)() )
|
Chris@102
|
1074 return true;
|
Chris@102
|
1075 if( null(a)() || null(b)() )
|
Chris@102
|
1076 return false;
|
Chris@102
|
1077 return (head(a)()==head(b)()) && (tail(a)()==tail(b)());
|
Chris@102
|
1078 }
|
Chris@102
|
1079 template <class T>
|
Chris@102
|
1080 bool operator==( const list<T>& a, const odd_list<T>& b ) {
|
Chris@102
|
1081 if( null(a)() && null(b)() )
|
Chris@102
|
1082 return true;
|
Chris@102
|
1083 if( null(a)() || null(b)() )
|
Chris@102
|
1084 return false;
|
Chris@102
|
1085 return (head(a)()==head(b)()) && (tail(a)()==tail(b)());
|
Chris@102
|
1086 }
|
Chris@102
|
1087 template <class T>
|
Chris@102
|
1088 bool operator==( const odd_list<T>& a, const list<T>& b ) {
|
Chris@102
|
1089 if( null(a)() && null(b)() )
|
Chris@102
|
1090 return true;
|
Chris@102
|
1091 if( null(a)() || null(b)() )
|
Chris@102
|
1092 return false;
|
Chris@102
|
1093 return (head(a)()==head(b)()) && (tail(a)()==tail(b)());
|
Chris@102
|
1094 }
|
Chris@102
|
1095
|
Chris@102
|
1096 template <class T>
|
Chris@102
|
1097 bool operator<( const list<T>& a, const list<T>& b ) {
|
Chris@102
|
1098 if( null(a)() && !null(b)() ) return true;
|
Chris@102
|
1099 if( null(b)() ) return false;
|
Chris@102
|
1100 if( head(b)() < head(a)() ) return false;
|
Chris@102
|
1101 if( head(a)() < head(b)() ) return true;
|
Chris@102
|
1102 return (tail(a)() < tail(b)());
|
Chris@102
|
1103 }
|
Chris@102
|
1104 template <class T>
|
Chris@102
|
1105 bool operator<( const odd_list<T>& a, const list<T>& b ) {
|
Chris@102
|
1106 if( null(a)() && !null(b)() ) return true;
|
Chris@102
|
1107 if( null(b)() ) return false;
|
Chris@102
|
1108 if( head(b)() < head(a)() ) return false;
|
Chris@102
|
1109 if( head(a)() < head(b)() ) return true;
|
Chris@102
|
1110 return (tail(a)() < tail(b)());
|
Chris@102
|
1111 }
|
Chris@102
|
1112 template <class T>
|
Chris@102
|
1113 bool operator<( const list<T>& a, const odd_list<T>& b ) {
|
Chris@102
|
1114 if( null(a) && !null(b) ) return true;
|
Chris@102
|
1115 if( null(b) ) return false;
|
Chris@102
|
1116 if( head(b) < head(a) ) return false;
|
Chris@102
|
1117 if( head(a) < head(b) ) return true;
|
Chris@102
|
1118 return (tail(a) < tail(b));
|
Chris@102
|
1119 }
|
Chris@102
|
1120 template <class T>
|
Chris@102
|
1121 bool operator<( const odd_list<T>& a, const odd_list<T>& b ) {
|
Chris@102
|
1122 if( null(a)() && !null(b)() ) return true;
|
Chris@102
|
1123 if( null(b)() ) return false;
|
Chris@102
|
1124 if( head(b)() < head(a)() ) return false;
|
Chris@102
|
1125 if( head(a)() < head(b)() ) return true;
|
Chris@102
|
1126 return (tail(a)() < tail(b)());
|
Chris@102
|
1127 }
|
Chris@102
|
1128 template <class T>
|
Chris@102
|
1129 bool operator<( const odd_list<T>&, a_unique_type_for_nil ) {
|
Chris@102
|
1130 return false;
|
Chris@102
|
1131 }
|
Chris@102
|
1132 template <class T>
|
Chris@102
|
1133 bool operator<( const list<T>&, a_unique_type_for_nil ) {
|
Chris@102
|
1134 return false;
|
Chris@102
|
1135 }
|
Chris@102
|
1136 template <class T>
|
Chris@102
|
1137 bool operator<( a_unique_type_for_nil, const odd_list<T>& b ) {
|
Chris@102
|
1138 return !null(b)();
|
Chris@102
|
1139 }
|
Chris@102
|
1140 template <class T>
|
Chris@102
|
1141 bool operator<( a_unique_type_for_nil, const list<T>& b ) {
|
Chris@102
|
1142 return !null(b)();
|
Chris@102
|
1143 }
|
Chris@102
|
1144
|
Chris@102
|
1145 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
1146 // Implement cat and cons after the list types are defined.
|
Chris@102
|
1147 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
1148 namespace impl {
|
Chris@102
|
1149 using listlike::ListLike;
|
Chris@102
|
1150
|
Chris@102
|
1151 template <class T, class F, class L>
|
Chris@102
|
1152 struct ConsHelp2<T,F,L,true>
|
Chris@102
|
1153 {
|
Chris@102
|
1154 typedef typename boost::remove_reference<T>::type TT;
|
Chris@102
|
1155 typedef typename L::force_result_type type;
|
Chris@102
|
1156 static type go( const TT& x, const F& f ) {
|
Chris@102
|
1157 return type( x, f );
|
Chris@102
|
1158 }
|
Chris@102
|
1159 };
|
Chris@102
|
1160 template <class T, class F>
|
Chris@102
|
1161 struct ConsHelp2<T,F,list<T>,true>
|
Chris@102
|
1162 {
|
Chris@102
|
1163 typedef typename boost::remove_reference<T>::type TT;
|
Chris@102
|
1164 typedef list<TT> L;
|
Chris@102
|
1165 typedef typename L::force_result_type type;
|
Chris@102
|
1166 static type go( const TT& x, const F& f ) {
|
Chris@102
|
1167 return odd_list<TT>(x, list<TT>(
|
Chris@102
|
1168 boost::intrusive_ptr<Cache<TT> >(new Cache<T>(
|
Chris@102
|
1169 typename Cache<TT>::CvtFxn(),f))));
|
Chris@102
|
1170 }
|
Chris@102
|
1171 };
|
Chris@102
|
1172 template <class T, class F>
|
Chris@102
|
1173 struct ConsHelp2<T,F,odd_list<T>,true>
|
Chris@102
|
1174 {
|
Chris@102
|
1175 typedef typename boost::remove_reference<T>::type TT;
|
Chris@102
|
1176 typedef odd_list<TT> L;
|
Chris@102
|
1177 typedef typename L::force_result_type type;
|
Chris@102
|
1178 static type go( const TT& x, const F& f ) {
|
Chris@102
|
1179 return odd_list<TT>(x, list<TT>( ListRaw(), new Cache<T>(f) ));
|
Chris@102
|
1180 }
|
Chris@102
|
1181 };
|
Chris@102
|
1182 template <class T, class F>
|
Chris@102
|
1183 struct ConsHelp2<T,F,a_unique_type_for_nil,false>
|
Chris@102
|
1184 {
|
Chris@102
|
1185 typedef typename boost::remove_reference<T>::type TT;
|
Chris@102
|
1186 typedef odd_list<TT> type;
|
Chris@102
|
1187 static type go( const TT& x, const F& f ) {
|
Chris@102
|
1188 return odd_list<TT>(x, list<TT>( ListRaw(), new Cache<T>(f) ));
|
Chris@102
|
1189 }
|
Chris@102
|
1190 };
|
Chris@102
|
1191
|
Chris@102
|
1192 template <class T, class L, bool b> struct ConsHelp1 {
|
Chris@102
|
1193 typedef typename boost::remove_reference<T>::type TT;
|
Chris@102
|
1194 typedef typename L::force_result_type type;
|
Chris@102
|
1195 static type go( const TT& x, const L& l ) {
|
Chris@102
|
1196 return type(x,l);
|
Chris@102
|
1197 }
|
Chris@102
|
1198 };
|
Chris@102
|
1199 template <class T> struct ConsHelp1<T,a_unique_type_for_nil,false> {
|
Chris@102
|
1200 typedef typename boost::remove_reference<T>::type TT;
|
Chris@102
|
1201 typedef odd_list<TT> type;
|
Chris@102
|
1202 static type go( const TT& x, const a_unique_type_for_nil& n ) {
|
Chris@102
|
1203 return type(x,n);
|
Chris@102
|
1204 }
|
Chris@102
|
1205 };
|
Chris@102
|
1206 template <class T, class F> struct ConsHelp1<T,F,false> {
|
Chris@102
|
1207 // It's a function returning a list
|
Chris@102
|
1208 // This is the one I have not fixed yet....
|
Chris@102
|
1209 // typedef typename F::result_type L;
|
Chris@102
|
1210 // typedef typename result_of::template ListType<F>::result_type L;
|
Chris@102
|
1211 typedef odd_list<T> L;
|
Chris@102
|
1212 typedef ConsHelp2<T,F,L,boost::is_base_and_derived<ListLike,L>::value> help;
|
Chris@102
|
1213 typedef typename help::type type;
|
Chris@102
|
1214 static type go( const T& x, const F& f ) {
|
Chris@102
|
1215 return help::go(x,f);
|
Chris@102
|
1216 }
|
Chris@102
|
1217 };
|
Chris@102
|
1218
|
Chris@102
|
1219 template <class T, class L, bool b>
|
Chris@102
|
1220 struct ConsHelp0;
|
Chris@102
|
1221
|
Chris@102
|
1222 template <class T>
|
Chris@102
|
1223 struct ConsHelp0<T,a_unique_type_for_nil,true> {
|
Chris@102
|
1224 typedef typename boost::remove_reference<T>::type TT;
|
Chris@102
|
1225 typedef odd_list<T> type;
|
Chris@102
|
1226 };
|
Chris@102
|
1227
|
Chris@102
|
1228 template <class T>
|
Chris@102
|
1229 struct ConsHelp0<const T &,const a_unique_type_for_nil &,true> {
|
Chris@102
|
1230 typedef typename boost::remove_reference<T>::type TT;
|
Chris@102
|
1231 typedef odd_list<TT> type;
|
Chris@102
|
1232 };
|
Chris@102
|
1233
|
Chris@102
|
1234 template <class T>
|
Chris@102
|
1235 struct ConsHelp0<T &,a_unique_type_for_nil &,true> {
|
Chris@102
|
1236 typedef typename boost::remove_reference<T>::type TT;
|
Chris@102
|
1237 typedef odd_list<TT> type;
|
Chris@102
|
1238 };
|
Chris@102
|
1239
|
Chris@102
|
1240 template <class T, class L>
|
Chris@102
|
1241 struct ConsHelp0<T,L,false> {
|
Chris@102
|
1242 // This removes any references from L for correct return type
|
Chris@102
|
1243 // identification.
|
Chris@102
|
1244 typedef typename boost::remove_reference<L>::type LType;
|
Chris@102
|
1245 typedef typename ConsHelp1<T,LType,
|
Chris@102
|
1246 boost::is_base_and_derived<ListLike,LType>::value>::type type;
|
Chris@102
|
1247 };
|
Chris@102
|
1248
|
Chris@102
|
1249 /////////////////////////////////////////////////////////////////////
|
Chris@102
|
1250 // cons (t,l) - cons a value to the front of a list.
|
Chris@102
|
1251 // Note: The first arg, t, must be a value.
|
Chris@102
|
1252 // The second arg, l, can be a list or NIL
|
Chris@102
|
1253 // or a function that returns a list.
|
Chris@102
|
1254 /////////////////////////////////////////////////////////////////////
|
Chris@102
|
1255 struct Cons
|
Chris@102
|
1256 {
|
Chris@102
|
1257 /* template <class T, class L> struct sig : public fun_type<
|
Chris@102
|
1258 typename ConsHelp1<T,L,
|
Chris@102
|
1259 boost::is_base_and_derived<ListLike,L>::value>::type> {};
|
Chris@102
|
1260 */
|
Chris@102
|
1261 template <typename Sig> struct result;
|
Chris@102
|
1262
|
Chris@102
|
1263 template <typename This, typename T, typename L>
|
Chris@102
|
1264 struct result<This(T, L)>
|
Chris@102
|
1265 {
|
Chris@102
|
1266 typedef typename ConsHelp0<T,L,
|
Chris@102
|
1267 listlike::detect_nil<L>::is_nil>::type type;
|
Chris@102
|
1268 };
|
Chris@102
|
1269
|
Chris@102
|
1270 template <typename This, typename T>
|
Chris@102
|
1271 struct result<This(T,a_unique_type_for_nil)>
|
Chris@102
|
1272 {
|
Chris@102
|
1273 typedef typename boost::remove_reference<T>::type TT;
|
Chris@102
|
1274 typedef odd_list<TT> type;
|
Chris@102
|
1275 };
|
Chris@102
|
1276
|
Chris@102
|
1277 template <typename T, typename L>
|
Chris@102
|
1278 typename result<Cons(T,L)>::type
|
Chris@102
|
1279 operator()( const T& x, const L& l ) const {
|
Chris@102
|
1280 typedef typename result<Cons(T,L)>::type LL;
|
Chris@102
|
1281 typedef typename result_of::ListType<L>::LType LType;
|
Chris@102
|
1282 typedef ConsHelp1<T,LType,
|
Chris@102
|
1283 boost::is_base_and_derived<ListLike,LType>::value> help;
|
Chris@102
|
1284 return help::go(x,l);
|
Chris@102
|
1285 }
|
Chris@102
|
1286
|
Chris@102
|
1287 template <typename T>
|
Chris@102
|
1288 typename result<Cons(T,a_unique_type_for_nil)>::type
|
Chris@102
|
1289 operator()( const T& x, const a_unique_type_for_nil &n ) const {
|
Chris@102
|
1290 typedef typename result<Cons(T,a_unique_type_for_nil)>::type LL;
|
Chris@102
|
1291 typedef ConsHelp1<T,LL,
|
Chris@102
|
1292 boost::is_base_and_derived<ListLike,LL>::value> help;
|
Chris@102
|
1293 return help::go(x,n);
|
Chris@102
|
1294 }
|
Chris@102
|
1295
|
Chris@102
|
1296 };
|
Chris@102
|
1297 }
|
Chris@102
|
1298
|
Chris@102
|
1299 typedef boost::phoenix::function<impl::Cons> Cons;
|
Chris@102
|
1300 Cons cons;
|
Chris@102
|
1301
|
Chris@102
|
1302 namespace impl {
|
Chris@102
|
1303
|
Chris@102
|
1304 template <class L, class M, bool b>
|
Chris@102
|
1305 struct CatHelp0;
|
Chris@102
|
1306
|
Chris@102
|
1307 template <class L>
|
Chris@102
|
1308 struct CatHelp0<L,a_unique_type_for_nil,true> {
|
Chris@102
|
1309 typedef typename result_of::template ListType<L>::LType type;
|
Chris@102
|
1310 };
|
Chris@102
|
1311
|
Chris@102
|
1312 template <class L>
|
Chris@102
|
1313 struct CatHelp0<const L &,const a_unique_type_for_nil &,true> {
|
Chris@102
|
1314 typedef typename result_of::template ListType<L>::LType type;
|
Chris@102
|
1315 //typedef L type;
|
Chris@102
|
1316 };
|
Chris@102
|
1317
|
Chris@102
|
1318 template <class L>
|
Chris@102
|
1319 struct CatHelp0<L &,a_unique_type_for_nil &,true> {
|
Chris@102
|
1320 typedef typename result_of::template ListType<L>::LType type;
|
Chris@102
|
1321 //typedef L type;
|
Chris@102
|
1322 };
|
Chris@102
|
1323
|
Chris@102
|
1324 template <class L, class M>
|
Chris@102
|
1325 struct CatHelp0<L,M,false> {
|
Chris@102
|
1326 // This removes any references from L for correct return type
|
Chris@102
|
1327 // identification.
|
Chris@102
|
1328 typedef typename result_of::template ListType<L>::LType type;
|
Chris@102
|
1329 // typedef typename ConsHelp1<T,LType,
|
Chris@102
|
1330 // boost::is_base_and_derived<ListLike,LType>::value>::type type;
|
Chris@102
|
1331 };
|
Chris@102
|
1332
|
Chris@102
|
1333 /////////////////////////////////////////////////////////////////////
|
Chris@102
|
1334 // cat (l,m) - concatenate lists.
|
Chris@102
|
1335 // Note: The first arg, l, must be a list or NIL.
|
Chris@102
|
1336 // The second arg, m, can be a list or NIL
|
Chris@102
|
1337 // or a function that returns a list.
|
Chris@102
|
1338 /////////////////////////////////////////////////////////////////////
|
Chris@102
|
1339 struct Cat
|
Chris@102
|
1340 {
|
Chris@102
|
1341 template <class L, class M, bool b, class R>
|
Chris@102
|
1342 struct Helper /*: public c_fun_type<L,M,R>*/ {
|
Chris@102
|
1343 template <typename Sig> struct result;
|
Chris@102
|
1344
|
Chris@102
|
1345 template <typename This>
|
Chris@102
|
1346 struct result<This(L,M)>
|
Chris@102
|
1347 {
|
Chris@102
|
1348 typedef typename result_of::ListType<L>::tail_result_type type;
|
Chris@102
|
1349 };
|
Chris@102
|
1350
|
Chris@102
|
1351 typedef R return_type;
|
Chris@102
|
1352 R operator()( const L& l, const M& m,
|
Chris@102
|
1353 reuser2<INV,VAR,INV,Helper,
|
Chris@102
|
1354 typename result_of::template ListType<L>::tail_result_type,M>
|
Chris@102
|
1355 r = NIL ) const {
|
Chris@102
|
1356 if( null(l)() )
|
Chris@102
|
1357 return m().force();
|
Chris@102
|
1358 else
|
Chris@102
|
1359 return cons( head(l)(), r( Helper<L,M,b,R>(), tail(l), m )() );
|
Chris@102
|
1360 }
|
Chris@102
|
1361 };
|
Chris@102
|
1362 template <class L, class M, class R>
|
Chris@102
|
1363 struct Helper<L,M,true,R> /*: public c_fun_type<L,M,R>*/ {
|
Chris@102
|
1364 template <typename Sig> struct result;
|
Chris@102
|
1365
|
Chris@102
|
1366 template <typename This>
|
Chris@102
|
1367 struct result<This(L,M)>
|
Chris@102
|
1368 {
|
Chris@102
|
1369 typedef typename result_of::ListType<L>::tail_result_type type;
|
Chris@102
|
1370 };
|
Chris@102
|
1371 typedef R return_type;
|
Chris@102
|
1372 R operator()( const L& l, const M& m,
|
Chris@102
|
1373 reuser2<INV,VAR,INV,Helper,
|
Chris@102
|
1374 typename result_of::template ListType<L>::tail_result_type,M>
|
Chris@102
|
1375 r = NIL ) const {
|
Chris@102
|
1376 if( null(l)() )
|
Chris@102
|
1377 return m.force();
|
Chris@102
|
1378 else
|
Chris@102
|
1379 return cons( head(l)(), r(Helper<L,M,true,R>(), tail(l), m )());
|
Chris@102
|
1380 }
|
Chris@102
|
1381 };
|
Chris@102
|
1382 template <class L, class R>
|
Chris@102
|
1383 struct Helper<L,a_unique_type_for_nil,false,R>
|
Chris@102
|
1384 /*: public c_fun_type<L,
|
Chris@102
|
1385 a_unique_type_for_nil,odd_list<typename L::value_type> > */
|
Chris@102
|
1386 {
|
Chris@102
|
1387 typedef odd_list<typename result_of::template ListType<L>::value_type> type;
|
Chris@102
|
1388 odd_list<typename result_of::template ListType<L>::value_type>
|
Chris@102
|
1389 operator()( const L& l, const a_unique_type_for_nil& ) const {
|
Chris@102
|
1390 return l;
|
Chris@102
|
1391 }
|
Chris@102
|
1392 };
|
Chris@102
|
1393 public:
|
Chris@102
|
1394 /*template <class L, class M> struct sig : public fun_type<
|
Chris@102
|
1395 typename RT<cons_type,typename L::value_type,M>::result_type>
|
Chris@102
|
1396 {}; */
|
Chris@102
|
1397 // Need to work out the return type here.
|
Chris@102
|
1398 template <typename Sig> struct result;
|
Chris@102
|
1399
|
Chris@102
|
1400 template <typename This, typename L, typename M>
|
Chris@102
|
1401 struct result<This(L,M)>
|
Chris@102
|
1402 {
|
Chris@102
|
1403 typedef typename CatHelp0<L,M,
|
Chris@102
|
1404 listlike::detect_nil<M>::is_nil>::type type;
|
Chris@102
|
1405 // typedef typename result_of::ListType<L>::tail_result_type type;
|
Chris@102
|
1406 };
|
Chris@102
|
1407
|
Chris@102
|
1408 template <typename This, typename L>
|
Chris@102
|
1409 struct result<This(L,a_unique_type_for_nil)>
|
Chris@102
|
1410 {
|
Chris@102
|
1411 typedef typename result_of::ListType<L>::tail_result_type type;
|
Chris@102
|
1412 };
|
Chris@102
|
1413 template <class L, class M>
|
Chris@102
|
1414 typename result<Cat(L,M)>::type operator()( const L& l, const M& m ) const
|
Chris@102
|
1415 {
|
Chris@102
|
1416 listlike::EnsureListLike<L>();
|
Chris@102
|
1417 return Helper<L,M,
|
Chris@102
|
1418 boost::is_base_and_derived<typename listlike::ListLike,M>::value,
|
Chris@102
|
1419 typename result<Cat(L,M)>::type>()(l,m);
|
Chris@102
|
1420 }
|
Chris@102
|
1421
|
Chris@102
|
1422 template <class L>
|
Chris@102
|
1423 typename result<Cat(L,a_unique_type_for_nil)>::type operator()( const L& l, const a_unique_type_for_nil& /* n */ ) const
|
Chris@102
|
1424 {
|
Chris@102
|
1425 listlike::EnsureListLike<L>();
|
Chris@102
|
1426 return l;
|
Chris@102
|
1427 }
|
Chris@102
|
1428
|
Chris@102
|
1429 };
|
Chris@102
|
1430
|
Chris@102
|
1431
|
Chris@102
|
1432 }
|
Chris@102
|
1433
|
Chris@102
|
1434 typedef boost::phoenix::function<impl::Cat> Cat;
|
Chris@102
|
1435 Cat cat;
|
Chris@102
|
1436
|
Chris@102
|
1437
|
Chris@102
|
1438 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
1439 // Handy functions for making list literals
|
Chris@102
|
1440 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
1441 // Yes, these aren't functoids, they're just template functions. I'm
|
Chris@102
|
1442 // lazy and created these mostly to make it easily to make little lists
|
Chris@102
|
1443 // in the sample code snippets that appear in papers.
|
Chris@102
|
1444
|
Chris@102
|
1445 struct UseList {
|
Chris@102
|
1446 template <class T> struct List { typedef list<T> type; };
|
Chris@102
|
1447 };
|
Chris@102
|
1448 struct UseOddList {
|
Chris@102
|
1449 template <class T> struct List { typedef odd_list<T> type; };
|
Chris@102
|
1450 };
|
Chris@102
|
1451 struct UseStrictList {
|
Chris@102
|
1452 template <class T> struct List { typedef strict_list<T> type; };
|
Chris@102
|
1453 };
|
Chris@102
|
1454
|
Chris@102
|
1455 template <class Kind = UseList>
|
Chris@102
|
1456 struct list_with {
|
Chris@102
|
1457 template <class T>
|
Chris@102
|
1458 typename Kind::template List<T>::type
|
Chris@102
|
1459 operator()( const T& a ) const {
|
Chris@102
|
1460 typename Kind::template List<T>::type l;
|
Chris@102
|
1461 l = cons( a, l );
|
Chris@102
|
1462 return l;
|
Chris@102
|
1463 }
|
Chris@102
|
1464
|
Chris@102
|
1465 template <class T>
|
Chris@102
|
1466 typename Kind::template List<T>::type
|
Chris@102
|
1467 operator()( const T& a, const T& b ) const {
|
Chris@102
|
1468 typename Kind::template List<T>::type l;
|
Chris@102
|
1469 l = cons( b, l );
|
Chris@102
|
1470 l = cons( a, l );
|
Chris@102
|
1471 return l;
|
Chris@102
|
1472 }
|
Chris@102
|
1473
|
Chris@102
|
1474 template <class T>
|
Chris@102
|
1475 typename Kind::template List<T>::type
|
Chris@102
|
1476 operator()( const T& a, const T& b, const T& c ) const {
|
Chris@102
|
1477 typename Kind::template List<T>::type l;
|
Chris@102
|
1478 l = cons( c, l );
|
Chris@102
|
1479 l = cons( b, l );
|
Chris@102
|
1480 l = cons( a, l );
|
Chris@102
|
1481 return l;
|
Chris@102
|
1482 }
|
Chris@102
|
1483
|
Chris@102
|
1484 template <class T>
|
Chris@102
|
1485 typename Kind::template List<T>::type
|
Chris@102
|
1486 operator()( const T& a, const T& b, const T& c, const T& d ) const {
|
Chris@102
|
1487 typename Kind::template List<T>::type l;
|
Chris@102
|
1488 l = cons( d, l );
|
Chris@102
|
1489 l = cons( c, l );
|
Chris@102
|
1490 l = cons( b, l );
|
Chris@102
|
1491 l = cons( a, l );
|
Chris@102
|
1492 return l;
|
Chris@102
|
1493 }
|
Chris@102
|
1494
|
Chris@102
|
1495 template <class T>
|
Chris@102
|
1496 typename Kind::template List<T>::type
|
Chris@102
|
1497 operator()( const T& a, const T& b, const T& c, const T& d,
|
Chris@102
|
1498 const T& e ) const {
|
Chris@102
|
1499 typename Kind::template List<T>::type l;
|
Chris@102
|
1500 l = cons( e, l );
|
Chris@102
|
1501 l = cons( d, l );
|
Chris@102
|
1502 l = cons( c, l );
|
Chris@102
|
1503 l = cons( b, l );
|
Chris@102
|
1504 l = cons( a, l );
|
Chris@102
|
1505 return l;
|
Chris@102
|
1506 }
|
Chris@102
|
1507 };
|
Chris@102
|
1508 //////////////////////////////////////////////////////////////////////
|
Chris@102
|
1509
|
Chris@102
|
1510 }
|
Chris@102
|
1511
|
Chris@102
|
1512 }
|
Chris@102
|
1513
|
Chris@102
|
1514 #endif
|