annotate DEPENDENCIES/generic/include/boost/phoenix/function/lazy_list.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents f46d142149f5
children
rev   line source
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