1 ////////////////////////////////////////////////////////////////////////////
4 // Build lazy operations for Phoenix equivalents for FC++
6 // These are equivalents of the Boost FC++ functoids in list.hpp
12 // strict_list<T> and associated iterator.
14 // list<T> and odd_list<T>
18 // Comparisons between list and odd_list types and separately for strict_list.
20 // NOTES: There is a fix at the moment as I have not yet sorted out
21 // how to get back the return type of a functor returning a list type.
22 // For the moment I have fixed this as odd_list<T> at two locations,
23 // one in list<T> and one in Cons. I am going to leave it like this
24 // for now as reading the code, odd_list<T> seems to be correct.
26 // I am also not happy at the details needed to detect types in Cons.
28 // I think the structure of this file is now complete.
29 // John Fletcher February 2015.
31 ////////////////////////////////////////////////////////////////////////////
32 /*=============================================================================
33 Copyright (c) 2000-2003 Brian McNamara and Yannis Smaragdakis
34 Copyright (c) 2001-2007 Joel de Guzman
35 Copyright (c) 2015 John Fletcher
37 Distributed under the Boost Software License, Version 1.0. (See accompanying
38 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
39 ==============================================================================*/
41 ///////////////////////////////////////////////////////////////////////
42 // This is from Boost FC++ list.hpp reimplemented without Fun0 or Full0
43 ///////////////////////////////////////////////////////////////////////
46 concept ListLike: Given a list representation type L
48 L<T> inherits ListLike and has
49 // typedefs just show typical values
51 typedef L<T> force_result_type
52 typedef L<T> delay_result_type
53 typedef L<T> tail_result_type
54 template <class UU> struct cons_rebind {
55 typedef L<UU> type; // force type
56 typedef L<UU> delay_type; // delay type
60 L( a_unique_type_for_nil )
61 template <class F> L(F) // F :: ()->L
63 constructor: force_result_type( T, L<T> )
65 constructor: force_result_type( T, F ) // F :: ()->L
70 // FIX THIS instead of operator bool(), does Boost have something better?
72 force_result_type force() const
73 delay_result_type delay() const
75 tail_result_type tail() const
77 static const bool is_lazy; // true if can represent infinite lists
79 typedef const_iterator;
80 typedef const_iterator iterator; // ListLikes are immutable
81 iterator begin() const
85 //////////////////////////////////////////////////////////////////////
86 // End of section from Boost FC++ list.hpp
87 //////////////////////////////////////////////////////////////////////
89 #ifndef BOOST_PHOENIX_FUNCTION_LAZY_LIST
90 #define BOOST_PHOENIX_FUNCTION_LAZY_LIST
92 #include <boost/phoenix/core.hpp>
93 #include <boost/phoenix/function.hpp>
94 #include <boost/intrusive_ptr.hpp>
95 #include <boost/function.hpp>
96 #include <boost/type_traits/type_with_alignment.hpp>
97 //#include "lazy_reuse.hpp"
103 //////////////////////////////////////////////////////////////////////
104 // These are the list types being declared.
105 //////////////////////////////////////////////////////////////////////
107 template <class T> class strict_list;
109 template <class T> class list;
110 template <class T> class odd_list;
112 // in ref_count.hpp in BoostFC++ now in lazy_operator.hpp
113 //typedef unsigned int RefCountType;
115 //////////////////////////////////////////////////////////////////////
116 // a_unique_type_for_nil moved to lazy_operator.hpp.
117 //////////////////////////////////////////////////////////////////////
120 //////////////////////////////////////////////////////////////////////
121 // Distinguish lazy lists (list and odd_list) from strict_list.
122 //////////////////////////////////////////////////////////////////////
125 // Copied from Boost FC++ list.hpp
126 template <class L, bool is_lazy> struct ensure_lazy_helper {};
127 template <class L> struct ensure_lazy_helper<L,true> {
128 static void requires_lazy_list_to_prevent_infinite_recursion() {}
132 ensure_lazy_helper<L,L::is_lazy>::
133 requires_lazy_list_to_prevent_infinite_recursion();
138 //////////////////////////////////////////////////////////////////////
139 // Provide remove reference for types defined for list types.
140 //////////////////////////////////////////////////////////////////////
142 namespace result_of {
144 template < typename L >
148 typedef typename boost::remove_reference<L>::type LType;
149 typedef typename LType::value_type value_type;
150 typedef typename LType::tail_result_type tail_result_type;
151 typedef typename LType::force_result_type force_result_type;
152 typedef typename LType::delay_result_type delay_result_type;
156 class ListType<a_unique_type_for_nil>
159 typedef a_unique_type_for_nil LType;
160 //typedef a_unique_type_for_nil value_type;
163 template <typename F, typename T>
165 typedef typename impl::odd_list<T> type;
170 //////////////////////////////////////////////////////////////////////
171 // ListLike is a property inherited by any list type to enable it to
172 // work with the functions being implemented in this file.
173 // It provides the check for the structure described above.
174 //////////////////////////////////////////////////////////////////////
178 struct ListLike {}; // This lets us use is_base_and_derived() to see
179 // (at compile-time) what classes are user-defined lists.
182 template <class L, bool is_lazy> struct ensure_lazy_helper {};
183 template <class L> struct ensure_lazy_helper<L,true> {
184 static void requires_lazy_list_to_prevent_infinite_recursion() {}
188 ensure_lazy_helper<L,L::is_lazy>::
189 requires_lazy_list_to_prevent_infinite_recursion();
192 template <class L, bool b>
193 struct EnsureListLikeHelp {
194 static void trying_to_call_a_list_function_on_a_non_list() {}
196 template <class L> struct EnsureListLikeHelp<L,false> { };
198 void EnsureListLike() {
199 typedef typename result_of::ListType<L>::LType LType;
200 EnsureListLikeHelp<L,boost::is_base_and_derived<ListLike,LType>::value>::
201 trying_to_call_a_list_function_on_a_non_list();
205 bool is_a_unique_type_for_nil(const L& /*l*/) {
210 bool is_a_unique_type_for_nil<a_unique_type_for_nil>
211 (const a_unique_type_for_nil& /* n */) {
217 static const bool is_nil = false;
221 struct detect_nil<a_unique_type_for_nil> {
222 static const bool is_nil = true;
226 struct detect_nil<a_unique_type_for_nil&> {
227 static const bool is_nil = true;
231 struct detect_nil<const a_unique_type_for_nil&> {
232 static const bool is_nil = true;
237 //////////////////////////////////////////////////////////////////////
238 // Implement lazy functions for list types. cat and cons come later.
239 //////////////////////////////////////////////////////////////////////
241 #ifndef BOOST_PHOENIX_FUNCTION_MAX_LAZY_LIST_LENGTH
242 #define BOOST_PHOENIX_FUNCTION_MAX_LAZY_LIST_LENGTH 1000
249 template <typename Sig>
252 template <typename This, typename L>
253 struct result<This(L)>
255 typedef typename result_of::ListType<L>::value_type type;
258 template <typename L>
259 typename result<Head(L)>::type
260 operator()(const L & l) const
262 listlike::EnsureListLike<L>();
270 template <typename Sig>
273 template <typename This, typename L>
274 struct result<This(L)>
276 typedef typename result_of::ListType<L>::tail_result_type type;
279 template <typename L>
280 typename result<Tail(L)>::type
281 operator()(const L & l) const
283 listlike::EnsureListLike<L>();
291 template <typename Sig>
294 template <typename This, typename L>
295 struct result<This(L)>
300 template <typename L>
301 typename result<Null(L)>::type
303 operator()(const L& l) const
305 listlike::EnsureListLike<L>();
312 template <typename Sig>
315 template <typename This, typename L>
316 struct result<This(L)>
318 typedef typename result_of::ListType<L>::delay_result_type type;
321 template <typename L>
322 typename result<Delay(L)>::type
323 operator()(const L & l) const
325 listlike::EnsureListLike<L>();
332 template <typename Sig>
335 template <typename This, typename L>
336 struct result<This(L)>
338 typedef typename result_of::ListType<L>::force_result_type type;
341 template <typename L>
342 typename result<Force(L)>::type
343 operator()(const L & l) const
345 listlike::EnsureListLike<L>();
352 //BOOST_PHOENIX_ADAPT_CALLABLE(head, impl::head, 1)
353 //BOOST_PHOENIX_ADAPT_CALLABLE(tail, impl::tail, 1)
354 //BOOST_PHOENIX_ADAPT_CALLABLE(null, impl::null, 1)
355 typedef boost::phoenix::function<impl::Head> Head;
356 typedef boost::phoenix::function<impl::Tail> Tail;
357 typedef boost::phoenix::function<impl::Null> Null;
358 typedef boost::phoenix::function<impl::Delay> Delay;
359 typedef boost::phoenix::function<impl::Force> Force;
366 //////////////////////////////////////////////////////////////////////
367 // These definitions used for strict_list are imported from BoostFC++
369 //////////////////////////////////////////////////////////////////////
373 struct strict_cons : public boost::noncopyable {
374 mutable RefCountType refC;
376 typedef boost::intrusive_ptr<strict_cons> tail_type;
378 strict_cons( const T& h, const tail_type& t ) : refC(0), head(h), tail(t) {}
382 void intrusive_ptr_add_ref( const strict_cons<T>* p ) {
386 void intrusive_ptr_release( const strict_cons<T>* p ) {
387 if( !--(p->refC) ) delete p;
391 class strict_list_iterator
392 : public std::iterator<std::input_iterator_tag,T,ptrdiff_t> {
393 typedef boost::intrusive_ptr<strict_cons<T> > rep_type;
401 class Proxy { // needed for operator->
403 friend class strict_list_iterator;
404 Proxy( const T& xx ) : x(xx) {}
406 const T* operator->() const { return &x; }
409 strict_list_iterator() : l(), is_nil(true) {}
410 explicit strict_list_iterator( const rep_type& ll ) : l(ll), is_nil(!ll) {}
412 const T operator*() const { return l->head; }
413 const Proxy operator->() const { return Proxy(l->head); }
414 strict_list_iterator<T>& operator++() {
418 const strict_list_iterator<T> operator++(int) {
419 strict_list_iterator<T> i( *this );
423 bool operator==( const strict_list_iterator<T>& i ) const {
424 return is_nil && i.is_nil;
426 bool operator!=( const strict_list_iterator<T>& i ) const {
427 return ! this->operator==(i);
432 //////////////////////////////////////////////////////////////////////
433 //////////////////////////////////////////////////////////////////////
436 class strict_list : public listlike::ListLike
438 typedef boost::intrusive_ptr<impl::strict_cons<T> > rep_type;
442 template <class Iter>
443 static rep_type help( Iter a, const Iter& b ) {
447 r = rep_type( new impl::strict_cons<T>( x, r ) );
454 static const bool is_lazy = false;
456 typedef T value_type;
457 typedef strict_list force_result_type;
458 typedef strict_list delay_result_type;
459 typedef strict_list tail_result_type;
460 template <class UU> struct cons_rebind {
461 typedef strict_list<UU> type;
462 typedef strict_list<UU> delay_type;
466 strict_list( Make, const rep_type& r ) : rep(r) {}
468 strict_list() : rep() {}
470 strict_list( a_unique_type_for_nil ) : rep() {}
473 strict_list( const F& f ) : rep( f().rep ) {
474 // I cannot do this yet.
475 //functoid_traits<F>::template ensure_accepts<0>::args();
478 strict_list( const T& x, const strict_list& y )
479 : rep( new impl::strict_cons<T>(x,y.rep) ) {}
482 strict_list( const T& x, const F& f )
483 : rep( new impl::strict_cons<T>(x,f().rep) ) {}
485 operator bool() const { return (bool)rep; }
486 force_result_type force() const { return *this; }
487 delay_result_type delay() const { return *this; }
489 #ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
491 throw lazy_exception("Tried to take head() of empty strict_list");
495 tail_result_type tail() const {
496 #ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
498 throw lazy_exception("Tried to take tail() of empty strict_list");
500 return strict_list(Make(),rep->tail);
503 template <class Iter>
504 strict_list( const Iter& a, const Iter& b ) : rep( rep_type() ) {
505 // How ironic. We need to reverse the iterator range in order to
506 // non-recursively build this!
507 std::vector<T> tmp(a,b);
508 rep = help( tmp.rbegin(), tmp.rend() );
511 // Since the strict_cons destructor can't call the strict_list
512 // destructor, the "simple" iterative destructor is correct and
513 // efficient. Hurray.
514 ~strict_list() { while(rep && (rep->refC == 1)) rep = rep->tail; }
516 // The following helps makes strict_list almost an STL "container"
517 typedef impl::strict_list_iterator<T> const_iterator;
518 typedef const_iterator iterator; // strict_list is immutable
519 iterator begin() const { return impl::strict_list_iterator<T>( rep ); }
520 iterator end() const { return impl::strict_list_iterator<T>(); }
524 // All of these null head and tail are now non lazy using e.g. null(a)().
525 // They need an extra () e.g. null(a)().
527 bool operator==( const strict_list<T>& a, a_unique_type_for_nil ) {
531 bool operator==( a_unique_type_for_nil, const strict_list<T>& a ) {
535 bool operator==( const strict_list<T>& a, const strict_list<T>& b ) {
536 if( null(a)() && null(b)() )
538 if( null(a)() || null(b)() )
540 return (head(a)()==head(b)()) &&
541 (tail(a)()==tail(b)());
545 bool operator<( const strict_list<T>& a, const strict_list<T>& b ) {
546 if( null(a)() && !null(b)() ) return true;
547 if( null(b)() ) return false;
548 if( head(b)() < head(a)() ) return false;
549 if( head(a)() < head(b)() ) return true;
550 return (tail(a)() < tail(b)());
553 bool operator<( const strict_list<T>&, a_unique_type_for_nil ) {
557 bool operator<( a_unique_type_for_nil, const strict_list<T>& b ) {
561 //////////////////////////////////////////////////////////////////////
562 // Class list<T> is the primary interface to the user for lazy lists.
563 //////////////////////////////////////////////////////////////////////{
569 struct CacheEmpty {};
571 template <class T> class Cache;
572 template <class T> class odd_list;
573 template <class T> class list_iterator;
574 template <class It, class T>
575 struct ListItHelp2 /*: public c_fun_type<It,It,odd_list<T> >*/ {
576 // This will need a return type.
577 typedef odd_list<T> return_type;
578 odd_list<T> operator()( It begin, const It& end,
579 reuser2<INV,VAR,INV,ListItHelp2<It,T>,It,It> r = NIL ) const;
581 template <class U,class F> struct cvt;
582 template <class T, class F, class R> struct ListHelp;
583 template <class T> Cache<T>* xempty_helper();
584 template <class T, class F, class L, bool b> struct ConsHelp2;
589 class list : public listlike::ListLike
591 // never NIL, unless an empty odd_list
592 boost::intrusive_ptr<Cache<T> > rep;
594 template <class U> friend class Cache;
595 template <class U> friend class odd_list;
596 template <class TT, class F, class L, bool b> friend struct ConsHelp2;
597 template <class U,class F> friend struct cvt;
599 list( const boost::intrusive_ptr<Cache<T> >& p ) : rep(p) { }
600 list( ListRaw, Cache<T>* p ) : rep(p) { }
602 bool priv_isEmpty() const {
603 return rep->cache().second.rep == Cache<T>::XNIL();
605 T priv_head() const {
606 #ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
608 throw lazy_exception("Tried to take head() of empty list");
610 return rep->cache().first();
612 list<T> priv_tail() const {
613 #ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
615 throw lazy_exception("Tried to take tail() of empty list");
617 return rep->cache().second;
622 static const bool is_lazy = true;
624 typedef T value_type;
625 typedef list tail_result_type;
626 typedef odd_list<T> force_result_type;
627 typedef list delay_result_type;
628 template <class UU> struct cons_rebind {
629 typedef odd_list<UU> type;
630 typedef list<UU> delay_type;
633 list( a_unique_type_for_nil ) : rep( Cache<T>::XEMPTY() ) { }
634 list() : rep( Cache<T>::XEMPTY() ) { }
636 template <class F> // works on both ()->odd_list and ()->list
637 // At the moment this is fixed for odd_list<T>.
638 // I need to do more work to get the general result.
640 : rep( ListHelp<T,F,odd_list<T> >()(f) ) { }
641 //: rep( ListHelp<T,F,typename F::result_type>()(f) ) { }
643 operator bool() const { return !priv_isEmpty(); }
644 const force_result_type& force() const { return rep->cache(); }
645 const delay_result_type& delay() const { return *this; }
646 // Note: force returns a reference;
647 // implicit conversion now returns a copy.
648 operator odd_list<T>() const { return force(); }
650 T head() const { return priv_head(); }
651 tail_result_type tail() const { return priv_tail(); }
653 // The following helps makes list almost an STL "container"
654 typedef list_iterator<T> const_iterator;
655 typedef const_iterator iterator; // list is immutable
656 iterator begin() const { return list_iterator<T>( *this ); }
657 iterator end() const { return list_iterator<T>(); }
662 //////////////////////////////////////////////////////////////////////
663 // Class odd_list<T> is not normally accessed by the user.
664 //////////////////////////////////////////////////////////////////////
666 struct OddListDummyY {};
669 class odd_list : public listlike::ListLike
673 typename boost::type_with_alignment<boost::alignment_of<T>::value>::type
676 union { xfst_type fst; unsigned char dummy[sizeof(T)]; };
678 const T& first() const {
679 return *static_cast<const T*>(static_cast<const void*>(&fst));
682 return *static_cast<T*>(static_cast<void*>(&fst));
684 list<T> second; // If XNIL, then this odd_list is NIL
686 template <class U> friend class list;
687 template <class U> friend class Cache;
689 odd_list( OddListDummyY )
690 : second( Cache<T>::XBAD() ) { }
692 void init( const T& x ) {
693 new (static_cast<void*>(&fst)) T(x);
696 bool fst_is_valid() const {
697 if( second.rep != Cache<T>::XNIL() )
698 if( second.rep != Cache<T>::XBAD() )
703 bool priv_isEmpty() const { return second.rep == Cache<T>::XNIL(); }
704 T priv_head() const {
705 #ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
707 throw lazy_exception("Tried to take head() of empty odd_list");
712 list<T> priv_tail() const {
713 #ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
715 throw lazy_exception("Tried to take tail() of empty odd_list");
721 static const bool is_lazy = true;
723 typedef T value_type;
724 typedef list<T> tail_result_type;
725 typedef odd_list<T> force_result_type;
726 typedef list<T> delay_result_type;
727 template <class UU> struct cons_rebind {
728 typedef odd_list<UU> type;
729 typedef list<UU> delay_type;
732 odd_list() : second( Cache<T>::XNIL() ) { }
733 odd_list( a_unique_type_for_nil ) : second( Cache<T>::XNIL() ) { }
734 odd_list( const T& x, const list<T>& y ) : second(y) { init(x); }
735 odd_list( const T& x, a_unique_type_for_nil ) : second(NIL) { init(x); }
737 odd_list( const odd_list<T>& x ) : second(x.second) {
738 if( fst_is_valid() ) {
744 odd_list( It begin, const It& end )
745 : second( begin==end ? Cache<T>::XNIL() :
746 ( init(*begin++), list<T>( begin, end ) ) ) {}
748 odd_list<T>& operator=( const odd_list<T>& x ) {
749 if( this == &x ) return *this;
750 if( fst_is_valid() ) {
751 if( x.fst_is_valid() )
757 if( x.fst_is_valid() )
765 if( fst_is_valid() ) {
770 operator bool() const { return !priv_isEmpty(); }
771 const force_result_type& force() const { return *this; }
772 delay_result_type delay() const { return list<T>(*this); }
774 T head() const { return priv_head(); }
775 tail_result_type tail() const { return priv_tail(); }
777 // The following helps makes odd_list almost an STL "container"
778 typedef list_iterator<T> const_iterator;
779 typedef const_iterator iterator; // odd_list is immutable
780 iterator begin() const { return list_iterator<T>( this->delay() ); }
781 iterator end() const { return list_iterator<T>(); }
783 // end of odd_list<T>
786 //////////////////////////////////////////////////////////////////////
788 //////////////////////////////////////////////////////////////////////
790 // This converts ()->list<T> to ()->odd_list<T>.
791 // In other words, here is the 'extra work' done when using the
792 // unoptimized interface.
793 template <class U,class F>
794 struct cvt /*: public c_fun_type<odd_list<U> >*/ {
795 typedef odd_list<U> return_type;
797 cvt( const F& ff ) : f(ff) {}
798 odd_list<U> operator()() const {
805 //////////////////////////////////////////////////////////////////////
806 // Cache<T> and associated functions.
807 //////////////////////////////////////////////////////////////////////
809 // I malloc a RefCountType to hold the refCount and init it to 1 to ensure the
810 // refCount will never get to 0, so the destructor-of-global-object
811 // order at the end of the program is a non-issue. In other words, the
812 // memory allocated here is only reclaimed by the operating system.
814 Cache<T>* xnil_helper() {
815 void *p = std::malloc( sizeof(RefCountType) );
816 *((RefCountType*)p) = 1;
817 return static_cast<Cache<T>*>( p );
821 Cache<T>* xnil_helper_nil() {
822 Cache<T>* p = xnil_helper<T>();
827 Cache<T>* xnil_helper_bad() {
828 Cache<T>* p = xnil_helper<T>();
833 Cache<T>* xempty_helper() {
834 Cache<T>* p = new Cache<T>( CacheEmpty() );
838 // This makes a boost phoenix function type with return type
841 struct fun0_type_helper{
842 typedef boost::function0<odd_list<T> > fun_type;
843 typedef boost::phoenix::function<fun_type> phx_type;
848 struct make_fun0_odd_list {
850 typedef typename fun0_type_helper<T>::fun_type fun_type;
851 typedef typename fun0_type_helper<T>::phx_type phx_type;
852 typedef phx_type result_type;
855 result_type operator()(const F& f) const
862 // Overload for the case where it is a boost phoenix function already.
864 typename boost::phoenix::function<F> operator()
865 (const boost::phoenix::function<F>& f) const
873 class Cache : boost::noncopyable {
874 mutable RefCountType refC;
875 // This is the boost::function type
876 typedef typename fun0_type_helper<T>::fun_type fun_odd_list_T;
877 // This is the boost::phoenix::function type;
878 typedef typename fun0_type_helper<T>::phx_type fun0_odd_list_T;
879 mutable fun0_odd_list_T fxn;
880 mutable odd_list<T> val;
881 // val.second.rep can be XBAD, XNIL, or a valid ptr
882 // - XBAD: val is invalid (fxn is valid)
883 // - XNIL: this is the empty list
884 // - anything else: val.first() is head, val.second is tail()
886 // This functoid should never be called; it represents a
887 // self-referent Cache, which should be impossible under the current
888 // implementation. Nonetheless, we need a 'dummy' function object to
889 // represent invalid 'fxn's (val.second.rep!=XBAD), and this
890 // implementation seems to be among the most reasonable.
891 struct blackhole_helper /*: c_fun_type< odd_list<T> >*/ {
892 typedef odd_list<T> return_type;
893 odd_list<T> operator()() const {
894 #ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
895 throw lazy_exception("You have entered a black hole.");
897 return odd_list<T>();
902 // Don't get rid of these XFOO() functions; they impose no overhead,
903 // and provide a useful place to add debugging code for tracking down
904 // before-main()-order-of-initialization problems.
905 static const boost::intrusive_ptr<Cache<T> >& XEMPTY() {
906 static boost::intrusive_ptr<Cache<T> > xempty( xempty_helper<T>() );
909 static const boost::intrusive_ptr<Cache<T> >& XNIL() {
911 static boost::intrusive_ptr<Cache<T> > xnil( xnil_helper_nil<T>() );
915 static const boost::intrusive_ptr<Cache<T> >& XBAD() {
916 // the pair is invalid; use fxn
917 static boost::intrusive_ptr<Cache<T> > xbad( xnil_helper_bad<T>() );
921 static fun0_odd_list_T /*<odd_list<T> >*/ the_blackhole;
922 static fun0_odd_list_T& blackhole() {
923 static fun0_odd_list_T the_blackhole;
924 //( make_fun0_odd_list<T>()( blackhole_helper() ) );
925 return the_blackhole;
928 odd_list<T>& cache() const {
929 if( val.second.rep == XBAD() ) {
936 template <class U> friend class list;
937 template <class U> friend class odd_list;
938 template <class TT, class F, class L, bool b> friend struct ConsHelp2;
939 template <class U,class F> friend struct cvt;
940 template <class U, class F, class R> friend struct ListHelp;
941 template <class U> friend Cache<U>* xempty_helper();
943 Cache( CacheEmpty ) : refC(0), fxn(blackhole()), val() {}
944 Cache( const odd_list<T>& x ) : refC(0), fxn(blackhole()), val(x) {}
945 Cache( const T& x, const list<T>& l ) : refC(0),fxn(blackhole()),val(x,l)
948 Cache( const fun0_odd_list_T& f )
949 : refC(0), fxn(f), val( OddListDummyY() ) {}
951 // f must be a boost phoenix function object?
953 Cache( const F& f ) // ()->odd_list
954 : refC(0), fxn(make_fun0_odd_list<T>()(f)), val( OddListDummyY() ) {}
956 // This is for ()->list<T> to ()->odd_list<T>
959 Cache( CvtFxn, const F& f ) // ()->list
960 : refC(0), fxn(make_fun0_odd_list<T>()(cvt<T,F>(f))), val( OddListDummyY() ) {}
963 friend void intrusive_ptr_add_ref( const Cache<X>* p );
965 friend void intrusive_ptr_release( const Cache<X>* p );
969 void intrusive_ptr_add_ref( const Cache<T>* p ) {
973 void intrusive_ptr_release( const Cache<T>* p ) {
974 if( !--(p->refC) ) delete p;
977 //////////////////////////////////////////////////////////////////////
978 // Rest of list's stuff
979 //////////////////////////////////////////////////////////////////////
981 template <class T, class F> struct ListHelp<T,F,list<T> > {
982 boost::intrusive_ptr<Cache<T> > operator()( const F& f ) const {
983 return boost::intrusive_ptr<Cache<T> >
984 (new Cache<T>(typename Cache<T>::CvtFxn(),f));
987 template <class T, class F> struct ListHelp<T,F,odd_list<T> > {
988 boost::intrusive_ptr<Cache<T> > operator()( const F& f ) const {
989 return boost::intrusive_ptr<Cache<T> >(new Cache<T>(f));
995 : public std::iterator<std::input_iterator_tag,T,ptrdiff_t> {
1003 class Proxy { // needed for operator->
1005 friend class list_iterator;
1006 Proxy( const T& xx ) : x(xx) {}
1008 const T* operator->() const { return &x; }
1011 list_iterator() : l(), is_nil(true) {}
1012 explicit list_iterator( const list<T>& ll ) : l(ll), is_nil(!ll) {}
1014 const T operator*() const { return l.head(); }
1015 const Proxy operator->() const { return Proxy(l.head()); }
1016 list_iterator<T>& operator++() {
1020 const list_iterator<T> operator++(int) {
1021 list_iterator<T> i( *this );
1025 bool operator==( const list_iterator<T>& i ) const {
1026 return is_nil && i.is_nil;
1028 bool operator!=( const list_iterator<T>& i ) const {
1029 return ! this->operator==(i);
1037 using impl::odd_list;
1038 using impl::list_iterator;
1040 //////////////////////////////////////////////////////////////////////
1041 // op== and op<, overloaded for all combos of list, odd_list, and NIL
1042 //////////////////////////////////////////////////////////////////////
1043 // All of these null head and tail are now non lazy using e.g. null(a)().
1044 // They need an extra () e.g. null(a)().
1046 // FIX THIS comparison operators can be implemented simpler with enable_if
1048 bool operator==( const odd_list<T>& a, a_unique_type_for_nil ) {
1052 bool operator==( const list<T>& a, a_unique_type_for_nil ) {
1056 bool operator==( a_unique_type_for_nil, const odd_list<T>& a ) {
1060 bool operator==( a_unique_type_for_nil, const list<T>& a ) {
1064 bool operator==( const list<T>& a, const list<T>& b ) {
1065 if( null(a)() && null(b)() )
1067 if( null(a)() || null(b)() )
1069 return (head(a)()==head(b)()) && (tail(a)()==tail(b)());
1072 bool operator==( const odd_list<T>& a, const odd_list<T>& b ) {
1073 if( null(a)() && null(b)() )
1075 if( null(a)() || null(b)() )
1077 return (head(a)()==head(b)()) && (tail(a)()==tail(b)());
1080 bool operator==( const list<T>& a, const odd_list<T>& b ) {
1081 if( null(a)() && null(b)() )
1083 if( null(a)() || null(b)() )
1085 return (head(a)()==head(b)()) && (tail(a)()==tail(b)());
1088 bool operator==( const odd_list<T>& a, const list<T>& b ) {
1089 if( null(a)() && null(b)() )
1091 if( null(a)() || null(b)() )
1093 return (head(a)()==head(b)()) && (tail(a)()==tail(b)());
1097 bool operator<( const list<T>& a, const list<T>& b ) {
1098 if( null(a)() && !null(b)() ) return true;
1099 if( null(b)() ) return false;
1100 if( head(b)() < head(a)() ) return false;
1101 if( head(a)() < head(b)() ) return true;
1102 return (tail(a)() < tail(b)());
1105 bool operator<( const odd_list<T>& a, const list<T>& b ) {
1106 if( null(a)() && !null(b)() ) return true;
1107 if( null(b)() ) return false;
1108 if( head(b)() < head(a)() ) return false;
1109 if( head(a)() < head(b)() ) return true;
1110 return (tail(a)() < tail(b)());
1113 bool operator<( const list<T>& a, const odd_list<T>& b ) {
1114 if( null(a) && !null(b) ) return true;
1115 if( null(b) ) return false;
1116 if( head(b) < head(a) ) return false;
1117 if( head(a) < head(b) ) return true;
1118 return (tail(a) < tail(b));
1121 bool operator<( const odd_list<T>& a, const odd_list<T>& b ) {
1122 if( null(a)() && !null(b)() ) return true;
1123 if( null(b)() ) return false;
1124 if( head(b)() < head(a)() ) return false;
1125 if( head(a)() < head(b)() ) return true;
1126 return (tail(a)() < tail(b)());
1129 bool operator<( const odd_list<T>&, a_unique_type_for_nil ) {
1133 bool operator<( const list<T>&, a_unique_type_for_nil ) {
1137 bool operator<( a_unique_type_for_nil, const odd_list<T>& b ) {
1141 bool operator<( a_unique_type_for_nil, const list<T>& b ) {
1145 //////////////////////////////////////////////////////////////////////
1146 // Implement cat and cons after the list types are defined.
1147 //////////////////////////////////////////////////////////////////////
1149 using listlike::ListLike;
1151 template <class T, class F, class L>
1152 struct ConsHelp2<T,F,L,true>
1154 typedef typename boost::remove_reference<T>::type TT;
1155 typedef typename L::force_result_type type;
1156 static type go( const TT& x, const F& f ) {
1157 return type( x, f );
1160 template <class T, class F>
1161 struct ConsHelp2<T,F,list<T>,true>
1163 typedef typename boost::remove_reference<T>::type TT;
1165 typedef typename L::force_result_type type;
1166 static type go( const TT& x, const F& f ) {
1167 return odd_list<TT>(x, list<TT>(
1168 boost::intrusive_ptr<Cache<TT> >(new Cache<T>(
1169 typename Cache<TT>::CvtFxn(),f))));
1172 template <class T, class F>
1173 struct ConsHelp2<T,F,odd_list<T>,true>
1175 typedef typename boost::remove_reference<T>::type TT;
1176 typedef odd_list<TT> L;
1177 typedef typename L::force_result_type type;
1178 static type go( const TT& x, const F& f ) {
1179 return odd_list<TT>(x, list<TT>( ListRaw(), new Cache<T>(f) ));
1182 template <class T, class F>
1183 struct ConsHelp2<T,F,a_unique_type_for_nil,false>
1185 typedef typename boost::remove_reference<T>::type TT;
1186 typedef odd_list<TT> type;
1187 static type go( const TT& x, const F& f ) {
1188 return odd_list<TT>(x, list<TT>( ListRaw(), new Cache<T>(f) ));
1192 template <class T, class L, bool b> struct ConsHelp1 {
1193 typedef typename boost::remove_reference<T>::type TT;
1194 typedef typename L::force_result_type type;
1195 static type go( const TT& x, const L& l ) {
1199 template <class T> struct ConsHelp1<T,a_unique_type_for_nil,false> {
1200 typedef typename boost::remove_reference<T>::type TT;
1201 typedef odd_list<TT> type;
1202 static type go( const TT& x, const a_unique_type_for_nil& n ) {
1206 template <class T, class F> struct ConsHelp1<T,F,false> {
1207 // It's a function returning a list
1208 // This is the one I have not fixed yet....
1209 // typedef typename F::result_type L;
1210 // typedef typename result_of::template ListType<F>::result_type L;
1211 typedef odd_list<T> L;
1212 typedef ConsHelp2<T,F,L,boost::is_base_and_derived<ListLike,L>::value> help;
1213 typedef typename help::type type;
1214 static type go( const T& x, const F& f ) {
1215 return help::go(x,f);
1219 template <class T, class L, bool b>
1223 struct ConsHelp0<T,a_unique_type_for_nil,true> {
1224 typedef typename boost::remove_reference<T>::type TT;
1225 typedef odd_list<T> type;
1229 struct ConsHelp0<const T &,const a_unique_type_for_nil &,true> {
1230 typedef typename boost::remove_reference<T>::type TT;
1231 typedef odd_list<TT> type;
1235 struct ConsHelp0<T &,a_unique_type_for_nil &,true> {
1236 typedef typename boost::remove_reference<T>::type TT;
1237 typedef odd_list<TT> type;
1240 template <class T, class L>
1241 struct ConsHelp0<T,L,false> {
1242 // This removes any references from L for correct return type
1244 typedef typename boost::remove_reference<L>::type LType;
1245 typedef typename ConsHelp1<T,LType,
1246 boost::is_base_and_derived<ListLike,LType>::value>::type type;
1249 /////////////////////////////////////////////////////////////////////
1250 // cons (t,l) - cons a value to the front of a list.
1251 // Note: The first arg, t, must be a value.
1252 // The second arg, l, can be a list or NIL
1253 // or a function that returns a list.
1254 /////////////////////////////////////////////////////////////////////
1257 /* template <class T, class L> struct sig : public fun_type<
1258 typename ConsHelp1<T,L,
1259 boost::is_base_and_derived<ListLike,L>::value>::type> {};
1261 template <typename Sig> struct result;
1263 template <typename This, typename T, typename L>
1264 struct result<This(T, L)>
1266 typedef typename ConsHelp0<T,L,
1267 listlike::detect_nil<L>::is_nil>::type type;
1270 template <typename This, typename T>
1271 struct result<This(T,a_unique_type_for_nil)>
1273 typedef typename boost::remove_reference<T>::type TT;
1274 typedef odd_list<TT> type;
1277 template <typename T, typename L>
1278 typename result<Cons(T,L)>::type
1279 operator()( const T& x, const L& l ) const {
1280 typedef typename result_of::ListType<L>::LType LType;
1281 typedef ConsHelp1<T,LType,
1282 boost::is_base_and_derived<ListLike,LType>::value> help;
1283 return help::go(x,l);
1286 template <typename T>
1287 typename result<Cons(T,a_unique_type_for_nil)>::type
1288 operator()( const T& x, const a_unique_type_for_nil &n ) const {
1289 typedef typename result<Cons(T,a_unique_type_for_nil)>::type LL;
1290 typedef ConsHelp1<T,LL,
1291 boost::is_base_and_derived<ListLike,LL>::value> help;
1292 return help::go(x,n);
1298 typedef boost::phoenix::function<impl::Cons> Cons;
1303 template <class L, class M, bool b>
1307 struct CatHelp0<LL,a_unique_type_for_nil,true> {
1308 typedef typename result_of::template ListType<LL>::LType type;
1312 struct CatHelp0<const LL &,const a_unique_type_for_nil &,true> {
1313 typedef typename result_of::template ListType<LL>::LType type;
1318 struct CatHelp0<LL &,a_unique_type_for_nil &,true> {
1319 typedef typename result_of::template ListType<LL>::LType type;
1323 template <class LL, class MM>
1324 struct CatHelp0<LL,MM,false> {
1325 // This removes any references from L for correct return type
1327 typedef typename result_of::template ListType<LL>::LType type;
1328 // typedef typename ConsHelp1<T,LType,
1329 // boost::is_base_and_derived<ListLike,LType>::value>::type type;
1332 /////////////////////////////////////////////////////////////////////
1333 // cat (l,m) - concatenate lists.
1334 // Note: The first arg, l, must be a list or NIL.
1335 // The second arg, m, can be a list or NIL
1336 // or a function that returns a list.
1337 /////////////////////////////////////////////////////////////////////
1340 template <class L, class M, bool b, class R>
1341 struct Helper /*: public c_fun_type<L,M,R>*/ {
1342 template <typename Sig> struct result;
1344 template <typename This>
1345 struct result<This(L,M)>
1347 typedef typename result_of::ListType<L>::tail_result_type type;
1350 typedef R return_type;
1351 R operator()( const L& l, const M& m,
1352 reuser2<INV,VAR,INV,Helper,
1353 typename result_of::template ListType<L>::tail_result_type,M>
1358 return cons( head(l)(), r( Helper<L,M,b,R>(), tail(l), m )() );
1361 template <class L, class M, class R>
1362 struct Helper<L,M,true,R> /*: public c_fun_type<L,M,R>*/ {
1363 template <typename Sig> struct result;
1365 template <typename This>
1366 struct result<This(L,M)>
1368 typedef typename result_of::ListType<L>::tail_result_type type;
1370 typedef R return_type;
1371 R operator()( const L& l, const M& m,
1372 reuser2<INV,VAR,INV,Helper,
1373 typename result_of::template ListType<L>::tail_result_type,M>
1378 return cons( head(l)(), r(Helper<L,M,true,R>(), tail(l), m )());
1381 template <class L, class R>
1382 struct Helper<L,a_unique_type_for_nil,false,R>
1383 /*: public c_fun_type<L,
1384 a_unique_type_for_nil,odd_list<typename L::value_type> > */
1386 typedef odd_list<typename result_of::template ListType<L>::value_type> type;
1387 odd_list<typename result_of::template ListType<L>::value_type>
1388 operator()( const L& l, const a_unique_type_for_nil& ) const {
1393 /*template <class L, class M> struct sig : public fun_type<
1394 typename RT<cons_type,typename L::value_type,M>::result_type>
1396 // Need to work out the return type here.
1397 template <typename Sig> struct result;
1399 template <typename This, typename L, typename M>
1400 struct result<This(L,M)>
1402 typedef typename CatHelp0<L,M,
1403 listlike::detect_nil<M>::is_nil>::type type;
1404 // typedef typename result_of::ListType<L>::tail_result_type type;
1407 template <typename This, typename L>
1408 struct result<This(L,a_unique_type_for_nil)>
1410 typedef typename result_of::ListType<L>::tail_result_type type;
1412 template <class L, class M>
1413 typename result<Cat(L,M)>::type operator()( const L& l, const M& m ) const
1415 listlike::EnsureListLike<L>();
1417 boost::is_base_and_derived<typename listlike::ListLike,M>::value,
1418 typename result<Cat(L,M)>::type>()(l,m);
1422 typename result<Cat(L,a_unique_type_for_nil)>::type operator()( const L& l, const a_unique_type_for_nil& /* n */ ) const
1424 listlike::EnsureListLike<L>();
1433 typedef boost::phoenix::function<impl::Cat> Cat;
1437 //////////////////////////////////////////////////////////////////////
1438 // Handy functions for making list literals
1439 //////////////////////////////////////////////////////////////////////
1440 // Yes, these aren't functoids, they're just template functions. I'm
1441 // lazy and created these mostly to make it easily to make little lists
1442 // in the sample code snippets that appear in papers.
1445 template <class T> struct List { typedef list<T> type; };
1448 template <class T> struct List { typedef odd_list<T> type; };
1450 struct UseStrictList {
1451 template <class T> struct List { typedef strict_list<T> type; };
1454 template <class Kind = UseList>
1457 typename Kind::template List<T>::type
1458 operator()( const T& a ) const {
1459 typename Kind::template List<T>::type l;
1465 typename Kind::template List<T>::type
1466 operator()( const T& a, const T& b ) const {
1467 typename Kind::template List<T>::type l;
1474 typename Kind::template List<T>::type
1475 operator()( const T& a, const T& b, const T& c ) const {
1476 typename Kind::template List<T>::type l;
1484 typename Kind::template List<T>::type
1485 operator()( const T& a, const T& b, const T& c, const T& d ) const {
1486 typename Kind::template List<T>::type l;
1495 typename Kind::template List<T>::type
1496 operator()( const T& a, const T& b, const T& c, const T& d,
1497 const T& e ) const {
1498 typename Kind::template List<T>::type l;
1507 //////////////////////////////////////////////////////////////////////