1524 lines
48 KiB
C++
1524 lines
48 KiB
C++
////////////////////////////////////////////////////////////////////////////
|
|
// lazy_list.hpp
|
|
//
|
|
// Build lazy operations for Phoenix equivalents for FC++
|
|
//
|
|
// These are equivalents of the Boost FC++ functoids in list.hpp
|
|
//
|
|
// Implemented so far:
|
|
//
|
|
// head tail null
|
|
//
|
|
// strict_list<T> and associated iterator.
|
|
//
|
|
// list<T> and odd_list<T>
|
|
//
|
|
// cons cat
|
|
//
|
|
// Comparisons between list and odd_list types and separately for strict_list.
|
|
//
|
|
// NOTES: There is a fix at the moment as I have not yet sorted out
|
|
// how to get back the return type of a functor returning a list type.
|
|
// For the moment I have fixed this as odd_list<T> at two locations,
|
|
// one in list<T> and one in Cons. I am going to leave it like this
|
|
// for now as reading the code, odd_list<T> seems to be correct.
|
|
//
|
|
// I am also not happy at the details needed to detect types in Cons.
|
|
//
|
|
// I think the structure of this file is now complete.
|
|
// John Fletcher February 2015.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
/*=============================================================================
|
|
Copyright (c) 2000-2003 Brian McNamara and Yannis Smaragdakis
|
|
Copyright (c) 2001-2007 Joel de Guzman
|
|
Copyright (c) 2015 John Fletcher
|
|
|
|
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
==============================================================================*/
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// This is from Boost FC++ list.hpp reimplemented without Fun0 or Full0
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
/*
|
|
concept ListLike: Given a list representation type L
|
|
|
|
L<T> inherits ListLike and has
|
|
// typedefs just show typical values
|
|
typedef T value_type
|
|
typedef L<T> force_result_type
|
|
typedef L<T> delay_result_type
|
|
typedef L<T> tail_result_type
|
|
template <class UU> struct cons_rebind {
|
|
typedef L<UU> type; // force type
|
|
typedef L<UU> delay_type; // delay type
|
|
};
|
|
|
|
L()
|
|
L( a_unique_type_for_nil )
|
|
template <class F> L(F) // F :: ()->L
|
|
|
|
constructor: force_result_type( T, L<T> )
|
|
template <class F>
|
|
constructor: force_result_type( T, F ) // F :: ()->L
|
|
|
|
template <class It>
|
|
L( It, It )
|
|
|
|
// FIX THIS instead of operator bool(), does Boost have something better?
|
|
operator bool() const
|
|
force_result_type force() const
|
|
delay_result_type delay() const
|
|
T head() const
|
|
tail_result_type tail() const
|
|
|
|
static const bool is_lazy; // true if can represent infinite lists
|
|
|
|
typedef const_iterator;
|
|
typedef const_iterator iterator; // ListLikes are immutable
|
|
iterator begin() const
|
|
iterator end() const
|
|
*/
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// End of section from Boost FC++ list.hpp
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#ifndef BOOST_PHOENIX_FUNCTION_LAZY_LIST
|
|
#define BOOST_PHOENIX_FUNCTION_LAZY_LIST
|
|
|
|
#include <boost/phoenix/core.hpp>
|
|
#include <boost/phoenix/function.hpp>
|
|
#include <boost/intrusive_ptr.hpp>
|
|
#include <boost/function.hpp>
|
|
#include <boost/type_traits/type_with_alignment.hpp>
|
|
//#include "lazy_reuse.hpp"
|
|
|
|
namespace boost {
|
|
|
|
namespace phoenix {
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// These are the list types being declared.
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
template <class T> class strict_list;
|
|
namespace impl {
|
|
template <class T> class list;
|
|
template <class T> class odd_list;
|
|
}
|
|
// in ref_count.hpp in BoostFC++ now in lazy_operator.hpp
|
|
//typedef unsigned int RefCountType;
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// a_unique_type_for_nil moved to lazy_operator.hpp.
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Distinguish lazy lists (list and odd_list) from strict_list.
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
namespace lazy {
|
|
// Copied from Boost FC++ list.hpp
|
|
template <class L, bool is_lazy> struct ensure_lazy_helper {};
|
|
template <class L> struct ensure_lazy_helper<L,true> {
|
|
static void requires_lazy_list_to_prevent_infinite_recursion() {}
|
|
};
|
|
template <class L>
|
|
void ensure_lazy() {
|
|
ensure_lazy_helper<L,L::is_lazy>::
|
|
requires_lazy_list_to_prevent_infinite_recursion();
|
|
}
|
|
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Provide remove reference for types defined for list types.
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
namespace result_of {
|
|
|
|
template < typename L >
|
|
class ListType
|
|
{
|
|
public:
|
|
typedef typename boost::remove_reference<L>::type LType;
|
|
typedef typename LType::value_type value_type;
|
|
typedef typename LType::tail_result_type tail_result_type;
|
|
typedef typename LType::force_result_type force_result_type;
|
|
typedef typename LType::delay_result_type delay_result_type;
|
|
};
|
|
|
|
template <>
|
|
class ListType<a_unique_type_for_nil>
|
|
{
|
|
public:
|
|
typedef a_unique_type_for_nil LType;
|
|
//typedef a_unique_type_for_nil value_type;
|
|
};
|
|
|
|
template <typename F, typename T>
|
|
struct ResultType {
|
|
typedef typename impl::odd_list<T> type;
|
|
};
|
|
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// ListLike is a property inherited by any list type to enable it to
|
|
// work with the functions being implemented in this file.
|
|
// It provides the check for the structure described above.
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
namespace listlike {
|
|
|
|
struct ListLike {}; // This lets us use is_base_and_derived() to see
|
|
// (at compile-time) what classes are user-defined lists.
|
|
|
|
|
|
template <class L, bool is_lazy> struct ensure_lazy_helper {};
|
|
template <class L> struct ensure_lazy_helper<L,true> {
|
|
static void requires_lazy_list_to_prevent_infinite_recursion() {}
|
|
};
|
|
template <class L>
|
|
void ensure_lazy() {
|
|
ensure_lazy_helper<L,L::is_lazy>::
|
|
requires_lazy_list_to_prevent_infinite_recursion();
|
|
}
|
|
|
|
template <class L, bool b>
|
|
struct EnsureListLikeHelp {
|
|
static void trying_to_call_a_list_function_on_a_non_list() {}
|
|
};
|
|
template <class L> struct EnsureListLikeHelp<L,false> { };
|
|
template <class L>
|
|
void EnsureListLike() {
|
|
typedef typename result_of::ListType<L>::LType LType;
|
|
EnsureListLikeHelp<L,boost::is_base_and_derived<ListLike,LType>::value>::
|
|
trying_to_call_a_list_function_on_a_non_list();
|
|
}
|
|
|
|
template <class L>
|
|
bool is_a_unique_type_for_nil(const L& /*l*/) {
|
|
return false;
|
|
}
|
|
|
|
template <>
|
|
bool is_a_unique_type_for_nil<a_unique_type_for_nil>
|
|
(const a_unique_type_for_nil& /* n */) {
|
|
return true;
|
|
}
|
|
|
|
template <class L>
|
|
struct detect_nil {
|
|
static const bool is_nil = false;
|
|
};
|
|
|
|
template <>
|
|
struct detect_nil<a_unique_type_for_nil> {
|
|
static const bool is_nil = true;
|
|
};
|
|
|
|
template <>
|
|
struct detect_nil<a_unique_type_for_nil&> {
|
|
static const bool is_nil = true;
|
|
};
|
|
|
|
template <>
|
|
struct detect_nil<const a_unique_type_for_nil&> {
|
|
static const bool is_nil = true;
|
|
};
|
|
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Implement lazy functions for list types. cat and cons come later.
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#ifndef BOOST_PHOENIX_FUNCTION_MAX_LAZY_LIST_LENGTH
|
|
#define BOOST_PHOENIX_FUNCTION_MAX_LAZY_LIST_LENGTH 1000
|
|
#endif
|
|
|
|
namespace impl {
|
|
|
|
struct Head
|
|
{
|
|
template <typename Sig>
|
|
struct result;
|
|
|
|
template <typename This, typename L>
|
|
struct result<This(L)>
|
|
{
|
|
typedef typename result_of::ListType<L>::value_type type;
|
|
};
|
|
|
|
template <typename L>
|
|
typename result<Head(L)>::type
|
|
operator()(const L & l) const
|
|
{
|
|
listlike::EnsureListLike<L>();
|
|
return l.head();
|
|
}
|
|
|
|
};
|
|
|
|
struct Tail
|
|
{
|
|
template <typename Sig>
|
|
struct result;
|
|
|
|
template <typename This, typename L>
|
|
struct result<This(L)>
|
|
{
|
|
typedef typename result_of::ListType<L>::tail_result_type type;
|
|
};
|
|
|
|
template <typename L>
|
|
typename result<Tail(L)>::type
|
|
operator()(const L & l) const
|
|
{
|
|
listlike::EnsureListLike<L>();
|
|
return l.tail();
|
|
}
|
|
|
|
};
|
|
|
|
struct Null
|
|
{
|
|
template <typename Sig>
|
|
struct result;
|
|
|
|
template <typename This, typename L>
|
|
struct result<This(L)>
|
|
{
|
|
typedef bool type;
|
|
};
|
|
|
|
template <typename L>
|
|
typename result<Null(L)>::type
|
|
//bool
|
|
operator()(const L& l) const
|
|
{
|
|
listlike::EnsureListLike<L>();
|
|
return !l;
|
|
}
|
|
|
|
};
|
|
|
|
struct Delay {
|
|
template <typename Sig>
|
|
struct result;
|
|
|
|
template <typename This, typename L>
|
|
struct result<This(L)>
|
|
{
|
|
typedef typename result_of::ListType<L>::delay_result_type type;
|
|
};
|
|
|
|
template <typename L>
|
|
typename result<Delay(L)>::type
|
|
operator()(const L & l) const
|
|
{
|
|
listlike::EnsureListLike<L>();
|
|
return l.delay();
|
|
}
|
|
|
|
};
|
|
|
|
struct Force {
|
|
template <typename Sig>
|
|
struct result;
|
|
|
|
template <typename This, typename L>
|
|
struct result<This(L)>
|
|
{
|
|
typedef typename result_of::ListType<L>::force_result_type type;
|
|
};
|
|
|
|
template <typename L>
|
|
typename result<Force(L)>::type
|
|
operator()(const L & l) const
|
|
{
|
|
listlike::EnsureListLike<L>();
|
|
return l.force();
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
//BOOST_PHOENIX_ADAPT_CALLABLE(head, impl::head, 1)
|
|
//BOOST_PHOENIX_ADAPT_CALLABLE(tail, impl::tail, 1)
|
|
//BOOST_PHOENIX_ADAPT_CALLABLE(null, impl::null, 1)
|
|
typedef boost::phoenix::function<impl::Head> Head;
|
|
typedef boost::phoenix::function<impl::Tail> Tail;
|
|
typedef boost::phoenix::function<impl::Null> Null;
|
|
typedef boost::phoenix::function<impl::Delay> Delay;
|
|
typedef boost::phoenix::function<impl::Force> Force;
|
|
Head head;
|
|
Tail tail;
|
|
Null null;
|
|
Delay delay;
|
|
Force force;
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// These definitions used for strict_list are imported from BoostFC++
|
|
// unchanged.
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
namespace impl {
|
|
template <class T>
|
|
struct strict_cons : public boost::noncopyable {
|
|
mutable RefCountType refC;
|
|
T head;
|
|
typedef boost::intrusive_ptr<strict_cons> tail_type;
|
|
tail_type tail;
|
|
strict_cons( const T& h, const tail_type& t ) : refC(0), head(h), tail(t) {}
|
|
|
|
};
|
|
template <class T>
|
|
void intrusive_ptr_add_ref( const strict_cons<T>* p ) {
|
|
++ (p->refC);
|
|
}
|
|
template <class T>
|
|
void intrusive_ptr_release( const strict_cons<T>* p ) {
|
|
if( !--(p->refC) ) delete p;
|
|
}
|
|
|
|
template <class T>
|
|
class strict_list_iterator {
|
|
typedef boost::intrusive_ptr<strict_cons<T> > rep_type;
|
|
rep_type l;
|
|
bool is_nil;
|
|
void advance() {
|
|
l = l->tail;
|
|
if( !l )
|
|
is_nil = true;
|
|
}
|
|
class Proxy { // needed for operator->
|
|
const T x;
|
|
friend class strict_list_iterator;
|
|
Proxy( const T& xx ) : x(xx) {}
|
|
public:
|
|
const T* operator->() const { return &x; }
|
|
};
|
|
public:
|
|
typedef std::input_iterator_tag iterator_category;
|
|
typedef T value_type;
|
|
typedef ptrdiff_t difference_type;
|
|
typedef T* pointer;
|
|
typedef T& reference;
|
|
|
|
strict_list_iterator() : l(), is_nil(true) {}
|
|
explicit strict_list_iterator( const rep_type& ll ) : l(ll), is_nil(!ll) {}
|
|
|
|
const T operator*() const { return l->head; }
|
|
const Proxy operator->() const { return Proxy(l->head); }
|
|
strict_list_iterator<T>& operator++() {
|
|
advance();
|
|
return *this;
|
|
}
|
|
const strict_list_iterator<T> operator++(int) {
|
|
strict_list_iterator<T> i( *this );
|
|
advance();
|
|
return i;
|
|
}
|
|
bool operator==( const strict_list_iterator<T>& i ) const {
|
|
return is_nil && i.is_nil;
|
|
}
|
|
bool operator!=( const strict_list_iterator<T>& i ) const {
|
|
return ! this->operator==(i);
|
|
}
|
|
};
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
template <class T>
|
|
class strict_list : public listlike::ListLike
|
|
{
|
|
typedef boost::intrusive_ptr<impl::strict_cons<T> > rep_type;
|
|
rep_type rep;
|
|
struct Make {};
|
|
|
|
template <class Iter>
|
|
static rep_type help( Iter a, const Iter& b ) {
|
|
rep_type r;
|
|
while( a != b ) {
|
|
T x( *a );
|
|
r = rep_type( new impl::strict_cons<T>( x, r ) );
|
|
++a;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
public:
|
|
static const bool is_lazy = false;
|
|
|
|
typedef T value_type;
|
|
typedef strict_list force_result_type;
|
|
typedef strict_list delay_result_type;
|
|
typedef strict_list tail_result_type;
|
|
template <class UU> struct cons_rebind {
|
|
typedef strict_list<UU> type;
|
|
typedef strict_list<UU> delay_type;
|
|
};
|
|
|
|
|
|
strict_list( Make, const rep_type& r ) : rep(r) {}
|
|
|
|
strict_list() : rep() {}
|
|
|
|
strict_list( a_unique_type_for_nil ) : rep() {}
|
|
|
|
template <class F>
|
|
strict_list( const F& f ) : rep( f().rep ) {
|
|
// I cannot do this yet.
|
|
//functoid_traits<F>::template ensure_accepts<0>::args();
|
|
}
|
|
|
|
strict_list( const T& x, const strict_list& y )
|
|
: rep( new impl::strict_cons<T>(x,y.rep) ) {}
|
|
|
|
template <class F>
|
|
strict_list( const T& x, const F& f )
|
|
: rep( new impl::strict_cons<T>(x,f().rep) ) {}
|
|
|
|
operator bool() const { return (bool)rep; }
|
|
force_result_type force() const { return *this; }
|
|
delay_result_type delay() const { return *this; }
|
|
T head() const {
|
|
#ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
|
|
if( !*this )
|
|
throw lazy_exception("Tried to take head() of empty strict_list");
|
|
#endif
|
|
return rep->head;
|
|
}
|
|
tail_result_type tail() const {
|
|
#ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
|
|
if( !*this )
|
|
throw lazy_exception("Tried to take tail() of empty strict_list");
|
|
#endif
|
|
return strict_list(Make(),rep->tail);
|
|
}
|
|
|
|
template <class Iter>
|
|
strict_list( const Iter& a, const Iter& b ) : rep( rep_type() ) {
|
|
// How ironic. We need to reverse the iterator range in order to
|
|
// non-recursively build this!
|
|
std::vector<T> tmp(a,b);
|
|
rep = help( tmp.rbegin(), tmp.rend() );
|
|
}
|
|
|
|
// Since the strict_cons destructor can't call the strict_list
|
|
// destructor, the "simple" iterative destructor is correct and
|
|
// efficient. Hurray.
|
|
~strict_list() { while(rep && (rep->refC == 1)) rep = rep->tail; }
|
|
|
|
// The following helps makes strict_list almost an STL "container"
|
|
typedef impl::strict_list_iterator<T> const_iterator;
|
|
typedef const_iterator iterator; // strict_list is immutable
|
|
iterator begin() const { return impl::strict_list_iterator<T>( rep ); }
|
|
iterator end() const { return impl::strict_list_iterator<T>(); }
|
|
|
|
};
|
|
|
|
// All of these null head and tail are now non lazy using e.g. null(a)().
|
|
// They need an extra () e.g. null(a)().
|
|
template <class T>
|
|
bool operator==( const strict_list<T>& a, a_unique_type_for_nil ) {
|
|
return null(a)();
|
|
}
|
|
template <class T>
|
|
bool operator==( a_unique_type_for_nil, const strict_list<T>& a ) {
|
|
return null(a)();
|
|
}
|
|
template <class T>
|
|
bool operator==( const strict_list<T>& a, const strict_list<T>& b ) {
|
|
if( null(a)() && null(b)() )
|
|
return true;
|
|
if( null(a)() || null(b)() )
|
|
return false;
|
|
return (head(a)()==head(b)()) &&
|
|
(tail(a)()==tail(b)());
|
|
}
|
|
|
|
template <class T>
|
|
bool operator<( const strict_list<T>& a, const strict_list<T>& b ) {
|
|
if( null(a)() && !null(b)() ) return true;
|
|
if( null(b)() ) return false;
|
|
if( head(b)() < head(a)() ) return false;
|
|
if( head(a)() < head(b)() ) return true;
|
|
return (tail(a)() < tail(b)());
|
|
}
|
|
template <class T>
|
|
bool operator<( const strict_list<T>&, a_unique_type_for_nil ) {
|
|
return false;
|
|
}
|
|
template <class T>
|
|
bool operator<( a_unique_type_for_nil, const strict_list<T>& b ) {
|
|
return !(null(b)());
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Class list<T> is the primary interface to the user for lazy lists.
|
|
//////////////////////////////////////////////////////////////////////{
|
|
namespace impl {
|
|
using fcpp::INV;
|
|
using fcpp::VAR;
|
|
using fcpp::reuser2;
|
|
|
|
struct CacheEmpty {};
|
|
|
|
template <class T> class Cache;
|
|
template <class T> class odd_list;
|
|
template <class T> class list_iterator;
|
|
template <class It, class T>
|
|
struct ListItHelp2 /*: public c_fun_type<It,It,odd_list<T> >*/ {
|
|
// This will need a return type.
|
|
typedef odd_list<T> return_type;
|
|
odd_list<T> operator()( It begin, const It& end,
|
|
reuser2<INV,VAR,INV,ListItHelp2<It,T>,It,It> r = NIL ) const;
|
|
};
|
|
template <class U,class F> struct cvt;
|
|
template <class T, class F, class R> struct ListHelp;
|
|
template <class T> Cache<T>* xempty_helper();
|
|
template <class T, class F, class L, bool b> struct ConsHelp2;
|
|
|
|
struct ListRaw {};
|
|
|
|
template <class T>
|
|
class list : public listlike::ListLike
|
|
{
|
|
// never NIL, unless an empty odd_list
|
|
boost::intrusive_ptr<Cache<T> > rep;
|
|
|
|
template <class U> friend class Cache;
|
|
template <class U> friend class odd_list;
|
|
template <class TT, class F, class L, bool b> friend struct ConsHelp2;
|
|
template <class U,class F> friend struct cvt;
|
|
|
|
list( const boost::intrusive_ptr<Cache<T> >& p ) : rep(p) { }
|
|
list( ListRaw, Cache<T>* p ) : rep(p) { }
|
|
|
|
bool priv_isEmpty() const {
|
|
return rep->cache().second.rep == Cache<T>::XNIL();
|
|
}
|
|
T priv_head() const {
|
|
#ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
|
|
if( priv_isEmpty() )
|
|
throw lazy_exception("Tried to take head() of empty list");
|
|
#endif
|
|
return rep->cache().first();
|
|
}
|
|
list<T> priv_tail() const {
|
|
#ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
|
|
if( priv_isEmpty() )
|
|
throw lazy_exception("Tried to take tail() of empty list");
|
|
#endif
|
|
return rep->cache().second;
|
|
}
|
|
|
|
|
|
public:
|
|
static const bool is_lazy = true;
|
|
|
|
typedef T value_type;
|
|
typedef list tail_result_type;
|
|
typedef odd_list<T> force_result_type;
|
|
typedef list delay_result_type;
|
|
template <class UU> struct cons_rebind {
|
|
typedef odd_list<UU> type;
|
|
typedef list<UU> delay_type;
|
|
};
|
|
|
|
list( a_unique_type_for_nil ) : rep( Cache<T>::XEMPTY() ) { }
|
|
list() : rep( Cache<T>::XEMPTY() ) { }
|
|
|
|
template <class F> // works on both ()->odd_list and ()->list
|
|
// At the moment this is fixed for odd_list<T>.
|
|
// I need to do more work to get the general result.
|
|
list( const F& f )
|
|
: rep( ListHelp<T,F,odd_list<T> >()(f) ) { }
|
|
//: rep( ListHelp<T,F,typename F::result_type>()(f) ) { }
|
|
|
|
operator bool() const { return !priv_isEmpty(); }
|
|
const force_result_type& force() const { return rep->cache(); }
|
|
const delay_result_type& delay() const { return *this; }
|
|
// Note: force returns a reference;
|
|
// implicit conversion now returns a copy.
|
|
operator odd_list<T>() const { return force(); }
|
|
|
|
T head() const { return priv_head(); }
|
|
tail_result_type tail() const { return priv_tail(); }
|
|
|
|
// The following helps makes list almost an STL "container"
|
|
typedef list_iterator<T> const_iterator;
|
|
typedef const_iterator iterator; // list is immutable
|
|
iterator begin() const { return list_iterator<T>( *this ); }
|
|
iterator end() const { return list_iterator<T>(); }
|
|
|
|
// end of list<T>
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Class odd_list<T> is not normally accessed by the user.
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
struct OddListDummyY {};
|
|
|
|
template <class T>
|
|
class odd_list : public listlike::ListLike
|
|
{
|
|
public:
|
|
typedef
|
|
typename boost::type_with_alignment<boost::alignment_of<T>::value>::type
|
|
xfst_type;
|
|
private:
|
|
union { xfst_type fst; unsigned char dummy[sizeof(T)]; };
|
|
|
|
const T& first() const {
|
|
return *static_cast<const T*>(static_cast<const void*>(&fst));
|
|
}
|
|
T& first() {
|
|
return *static_cast<T*>(static_cast<void*>(&fst));
|
|
}
|
|
list<T> second; // If XNIL, then this odd_list is NIL
|
|
|
|
template <class U> friend class list;
|
|
template <class U> friend class Cache;
|
|
|
|
odd_list( OddListDummyY )
|
|
: second( Cache<T>::XBAD() ) { }
|
|
|
|
void init( const T& x ) {
|
|
new (static_cast<void*>(&fst)) T(x);
|
|
}
|
|
|
|
bool fst_is_valid() const {
|
|
if( second.rep != Cache<T>::XNIL() )
|
|
if( second.rep != Cache<T>::XBAD() )
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
bool priv_isEmpty() const { return second.rep == Cache<T>::XNIL(); }
|
|
T priv_head() const {
|
|
#ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
|
|
if( priv_isEmpty() )
|
|
throw lazy_exception("Tried to take head() of empty odd_list");
|
|
#endif
|
|
return first();
|
|
}
|
|
|
|
list<T> priv_tail() const {
|
|
#ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
|
|
if( priv_isEmpty() )
|
|
throw lazy_exception("Tried to take tail() of empty odd_list");
|
|
#endif
|
|
return second;
|
|
}
|
|
|
|
public:
|
|
static const bool is_lazy = true;
|
|
|
|
typedef T value_type;
|
|
typedef list<T> tail_result_type;
|
|
typedef odd_list<T> force_result_type;
|
|
typedef list<T> delay_result_type;
|
|
template <class UU> struct cons_rebind {
|
|
typedef odd_list<UU> type;
|
|
typedef list<UU> delay_type;
|
|
};
|
|
|
|
odd_list() : second( Cache<T>::XNIL() ) { }
|
|
odd_list( a_unique_type_for_nil ) : second( Cache<T>::XNIL() ) { }
|
|
odd_list( const T& x, const list<T>& y ) : second(y) { init(x); }
|
|
odd_list( const T& x, a_unique_type_for_nil ) : second(NIL) { init(x); }
|
|
|
|
odd_list( const odd_list<T>& x ) : second(x.second) {
|
|
if( fst_is_valid() ) {
|
|
init( x.first() );
|
|
}
|
|
}
|
|
|
|
template <class It>
|
|
odd_list( It begin, const It& end )
|
|
: second( begin==end ? Cache<T>::XNIL() :
|
|
( init(*begin++), list<T>( begin, end ) ) ) {}
|
|
|
|
odd_list<T>& operator=( const odd_list<T>& x ) {
|
|
if( this == &x ) return *this;
|
|
if( fst_is_valid() ) {
|
|
if( x.fst_is_valid() )
|
|
first() = x.first();
|
|
else
|
|
first().~T();
|
|
}
|
|
else {
|
|
if( x.fst_is_valid() )
|
|
init( x.first() );
|
|
}
|
|
second = x.second;
|
|
return *this;
|
|
}
|
|
|
|
~odd_list() {
|
|
if( fst_is_valid() ) {
|
|
first().~T();
|
|
}
|
|
}
|
|
|
|
operator bool() const { return !priv_isEmpty(); }
|
|
const force_result_type& force() const { return *this; }
|
|
delay_result_type delay() const { return list<T>(*this); }
|
|
|
|
T head() const { return priv_head(); }
|
|
tail_result_type tail() const { return priv_tail(); }
|
|
|
|
// The following helps makes odd_list almost an STL "container"
|
|
typedef list_iterator<T> const_iterator;
|
|
typedef const_iterator iterator; // odd_list is immutable
|
|
iterator begin() const { return list_iterator<T>( this->delay() ); }
|
|
iterator end() const { return list_iterator<T>(); }
|
|
|
|
// end of odd_list<T>
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// struct cvt
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
// This converts ()->list<T> to ()->odd_list<T>.
|
|
// In other words, here is the 'extra work' done when using the
|
|
// unoptimized interface.
|
|
template <class U,class F>
|
|
struct cvt /*: public c_fun_type<odd_list<U> >*/ {
|
|
typedef odd_list<U> return_type;
|
|
F f;
|
|
cvt( const F& ff ) : f(ff) {}
|
|
odd_list<U> operator()() const {
|
|
list<U> l = f();
|
|
return l.force();
|
|
}
|
|
};
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Cache<T> and associated functions.
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
// I malloc a RefCountType to hold the refCount and init it to 1 to ensure the
|
|
// refCount will never get to 0, so the destructor-of-global-object
|
|
// order at the end of the program is a non-issue. In other words, the
|
|
// memory allocated here is only reclaimed by the operating system.
|
|
template <class T>
|
|
Cache<T>* xnil_helper() {
|
|
void *p = std::malloc( sizeof(RefCountType) );
|
|
*((RefCountType*)p) = 1;
|
|
return static_cast<Cache<T>*>( p );
|
|
}
|
|
|
|
template <class T>
|
|
Cache<T>* xnil_helper_nil() {
|
|
Cache<T>* p = xnil_helper<T>();
|
|
return p;
|
|
}
|
|
|
|
template <class T>
|
|
Cache<T>* xnil_helper_bad() {
|
|
Cache<T>* p = xnil_helper<T>();
|
|
return p;
|
|
}
|
|
|
|
template <class T>
|
|
Cache<T>* xempty_helper() {
|
|
Cache<T>* p = new Cache<T>( CacheEmpty() );
|
|
return p;
|
|
}
|
|
|
|
// This makes a boost phoenix function type with return type
|
|
// odd_list<T>
|
|
template <class T>
|
|
struct fun0_type_helper{
|
|
typedef boost::function0<odd_list<T> > fun_type;
|
|
typedef boost::phoenix::function<fun_type> phx_type;
|
|
};
|
|
|
|
|
|
template <class T>
|
|
struct make_fun0_odd_list {
|
|
|
|
typedef typename fun0_type_helper<T>::fun_type fun_type;
|
|
typedef typename fun0_type_helper<T>::phx_type phx_type;
|
|
typedef phx_type result_type;
|
|
|
|
template <class F>
|
|
result_type operator()(const F& f) const
|
|
{
|
|
fun_type ff(f);
|
|
phx_type g(ff);
|
|
return g;
|
|
}
|
|
|
|
// Overload for the case where it is a boost phoenix function already.
|
|
template <class F>
|
|
typename boost::phoenix::function<F> operator()
|
|
(const boost::phoenix::function<F>& f) const
|
|
{
|
|
return f;
|
|
}
|
|
|
|
};
|
|
|
|
template <class T>
|
|
class Cache : boost::noncopyable {
|
|
mutable RefCountType refC;
|
|
// This is the boost::function type
|
|
typedef typename fun0_type_helper<T>::fun_type fun_odd_list_T;
|
|
// This is the boost::phoenix::function type;
|
|
typedef typename fun0_type_helper<T>::phx_type fun0_odd_list_T;
|
|
mutable fun0_odd_list_T fxn;
|
|
mutable odd_list<T> val;
|
|
// val.second.rep can be XBAD, XNIL, or a valid ptr
|
|
// - XBAD: val is invalid (fxn is valid)
|
|
// - XNIL: this is the empty list
|
|
// - anything else: val.first() is head, val.second is tail()
|
|
|
|
// This functoid should never be called; it represents a
|
|
// self-referent Cache, which should be impossible under the current
|
|
// implementation. Nonetheless, we need a 'dummy' function object to
|
|
// represent invalid 'fxn's (val.second.rep!=XBAD), and this
|
|
// implementation seems to be among the most reasonable.
|
|
struct blackhole_helper /*: c_fun_type< odd_list<T> >*/ {
|
|
typedef odd_list<T> return_type;
|
|
odd_list<T> operator()() const {
|
|
#ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
|
|
throw lazy_exception("You have entered a black hole.");
|
|
#else
|
|
return odd_list<T>();
|
|
#endif
|
|
}
|
|
};
|
|
|
|
// Don't get rid of these XFOO() functions; they impose no overhead,
|
|
// and provide a useful place to add debugging code for tracking down
|
|
// before-main()-order-of-initialization problems.
|
|
static const boost::intrusive_ptr<Cache<T> >& XEMPTY() {
|
|
static boost::intrusive_ptr<Cache<T> > xempty( xempty_helper<T>() );
|
|
return xempty;
|
|
}
|
|
static const boost::intrusive_ptr<Cache<T> >& XNIL() {
|
|
// this list is nil
|
|
static boost::intrusive_ptr<Cache<T> > xnil( xnil_helper_nil<T>() );
|
|
return xnil;
|
|
}
|
|
|
|
static const boost::intrusive_ptr<Cache<T> >& XBAD() {
|
|
// the pair is invalid; use fxn
|
|
static boost::intrusive_ptr<Cache<T> > xbad( xnil_helper_bad<T>() );
|
|
return xbad;
|
|
}
|
|
|
|
static fun0_odd_list_T /*<odd_list<T> >*/ the_blackhole;
|
|
static fun0_odd_list_T& blackhole() {
|
|
static fun0_odd_list_T the_blackhole;
|
|
//( make_fun0_odd_list<T>()( blackhole_helper() ) );
|
|
return the_blackhole;
|
|
}
|
|
|
|
odd_list<T>& cache() const {
|
|
if( val.second.rep == XBAD() ) {
|
|
val = fxn()();
|
|
fxn = blackhole();
|
|
}
|
|
return val;
|
|
}
|
|
|
|
template <class U> friend class list;
|
|
template <class U> friend class odd_list;
|
|
template <class TT, class F, class L, bool b> friend struct ConsHelp2;
|
|
template <class U,class F> friend struct cvt;
|
|
template <class U, class F, class R> friend struct ListHelp;
|
|
template <class U> friend Cache<U>* xempty_helper();
|
|
|
|
Cache( CacheEmpty ) : refC(0), fxn(blackhole()), val() {}
|
|
Cache( const odd_list<T>& x ) : refC(0), fxn(blackhole()), val(x) {}
|
|
Cache( const T& x, const list<T>& l ) : refC(0),fxn(blackhole()),val(x,l)
|
|
{}
|
|
|
|
Cache( const fun0_odd_list_T& f )
|
|
: refC(0), fxn(f), val( OddListDummyY() ) {}
|
|
|
|
// f must be a boost phoenix function object?
|
|
template <class F>
|
|
Cache( const F& f ) // ()->odd_list
|
|
: refC(0), fxn(make_fun0_odd_list<T>()(f)), val( OddListDummyY() ) {}
|
|
|
|
// This is for ()->list<T> to ()->odd_list<T>
|
|
struct CvtFxn {};
|
|
template <class F>
|
|
Cache( CvtFxn, const F& f ) // ()->list
|
|
: refC(0), fxn(make_fun0_odd_list<T>()(cvt<T,F>(f))), val( OddListDummyY() ) {}
|
|
|
|
template <class X>
|
|
friend void intrusive_ptr_add_ref( const Cache<X>* p );
|
|
template <class X>
|
|
friend void intrusive_ptr_release( const Cache<X>* p );
|
|
};
|
|
|
|
template <class T>
|
|
void intrusive_ptr_add_ref( const Cache<T>* p ) {
|
|
++ (p->refC);
|
|
}
|
|
template <class T>
|
|
void intrusive_ptr_release( const Cache<T>* p ) {
|
|
if( !--(p->refC) ) delete p;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Rest of list's stuff
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
template <class T, class F> struct ListHelp<T,F,list<T> > {
|
|
boost::intrusive_ptr<Cache<T> > operator()( const F& f ) const {
|
|
return boost::intrusive_ptr<Cache<T> >
|
|
(new Cache<T>(typename Cache<T>::CvtFxn(),f));
|
|
}
|
|
};
|
|
template <class T, class F> struct ListHelp<T,F,odd_list<T> > {
|
|
boost::intrusive_ptr<Cache<T> > operator()( const F& f ) const {
|
|
return boost::intrusive_ptr<Cache<T> >(new Cache<T>(f));
|
|
}
|
|
};
|
|
|
|
template <class T>
|
|
class list_iterator {
|
|
list<T> l;
|
|
bool is_nil;
|
|
void advance() {
|
|
l = l.tail();
|
|
if( !l )
|
|
is_nil = true;
|
|
}
|
|
class Proxy { // needed for operator->
|
|
const T x;
|
|
friend class list_iterator;
|
|
Proxy( const T& xx ) : x(xx) {}
|
|
public:
|
|
const T* operator->() const { return &x; }
|
|
};
|
|
public:
|
|
typedef std::input_iterator_tag iterator_category;
|
|
typedef T value_type;
|
|
typedef ptrdiff_t difference_type;
|
|
typedef T* pointer;
|
|
typedef T& reference;
|
|
|
|
list_iterator() : l(), is_nil(true) {}
|
|
explicit list_iterator( const list<T>& ll ) : l(ll), is_nil(!ll) {}
|
|
|
|
const T operator*() const { return l.head(); }
|
|
const Proxy operator->() const { return Proxy(l.head()); }
|
|
list_iterator<T>& operator++() {
|
|
advance();
|
|
return *this;
|
|
}
|
|
const list_iterator<T> operator++(int) {
|
|
list_iterator<T> i( *this );
|
|
advance();
|
|
return i;
|
|
}
|
|
bool operator==( const list_iterator<T>& i ) const {
|
|
return is_nil && i.is_nil;
|
|
}
|
|
bool operator!=( const list_iterator<T>& i ) const {
|
|
return ! this->operator==(i);
|
|
}
|
|
};
|
|
|
|
|
|
} // namespace impl
|
|
|
|
using impl::list;
|
|
using impl::odd_list;
|
|
using impl::list_iterator;
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// op== and op<, overloaded for all combos of list, odd_list, and NIL
|
|
//////////////////////////////////////////////////////////////////////
|
|
// All of these null head and tail are now non lazy using e.g. null(a)().
|
|
// They need an extra () e.g. null(a)().
|
|
|
|
// FIX THIS comparison operators can be implemented simpler with enable_if
|
|
template <class T>
|
|
bool operator==( const odd_list<T>& a, a_unique_type_for_nil ) {
|
|
return null(a)();
|
|
}
|
|
template <class T>
|
|
bool operator==( const list<T>& a, a_unique_type_for_nil ) {
|
|
return null(a)();
|
|
}
|
|
template <class T>
|
|
bool operator==( a_unique_type_for_nil, const odd_list<T>& a ) {
|
|
return null(a)();
|
|
}
|
|
template <class T>
|
|
bool operator==( a_unique_type_for_nil, const list<T>& a ) {
|
|
return null(a)();
|
|
}
|
|
template <class T>
|
|
bool operator==( const list<T>& a, const list<T>& b ) {
|
|
if( null(a)() && null(b)() )
|
|
return true;
|
|
if( null(a)() || null(b)() )
|
|
return false;
|
|
return (head(a)()==head(b)()) && (tail(a)()==tail(b)());
|
|
}
|
|
template <class T>
|
|
bool operator==( const odd_list<T>& a, const odd_list<T>& b ) {
|
|
if( null(a)() && null(b)() )
|
|
return true;
|
|
if( null(a)() || null(b)() )
|
|
return false;
|
|
return (head(a)()==head(b)()) && (tail(a)()==tail(b)());
|
|
}
|
|
template <class T>
|
|
bool operator==( const list<T>& a, const odd_list<T>& b ) {
|
|
if( null(a)() && null(b)() )
|
|
return true;
|
|
if( null(a)() || null(b)() )
|
|
return false;
|
|
return (head(a)()==head(b)()) && (tail(a)()==tail(b)());
|
|
}
|
|
template <class T>
|
|
bool operator==( const odd_list<T>& a, const list<T>& b ) {
|
|
if( null(a)() && null(b)() )
|
|
return true;
|
|
if( null(a)() || null(b)() )
|
|
return false;
|
|
return (head(a)()==head(b)()) && (tail(a)()==tail(b)());
|
|
}
|
|
|
|
template <class T>
|
|
bool operator<( const list<T>& a, const list<T>& b ) {
|
|
if( null(a)() && !null(b)() ) return true;
|
|
if( null(b)() ) return false;
|
|
if( head(b)() < head(a)() ) return false;
|
|
if( head(a)() < head(b)() ) return true;
|
|
return (tail(a)() < tail(b)());
|
|
}
|
|
template <class T>
|
|
bool operator<( const odd_list<T>& a, const list<T>& b ) {
|
|
if( null(a)() && !null(b)() ) return true;
|
|
if( null(b)() ) return false;
|
|
if( head(b)() < head(a)() ) return false;
|
|
if( head(a)() < head(b)() ) return true;
|
|
return (tail(a)() < tail(b)());
|
|
}
|
|
template <class T>
|
|
bool operator<( const list<T>& a, const odd_list<T>& b ) {
|
|
if( null(a) && !null(b) ) return true;
|
|
if( null(b) ) return false;
|
|
if( head(b) < head(a) ) return false;
|
|
if( head(a) < head(b) ) return true;
|
|
return (tail(a) < tail(b));
|
|
}
|
|
template <class T>
|
|
bool operator<( const odd_list<T>& a, const odd_list<T>& b ) {
|
|
if( null(a)() && !null(b)() ) return true;
|
|
if( null(b)() ) return false;
|
|
if( head(b)() < head(a)() ) return false;
|
|
if( head(a)() < head(b)() ) return true;
|
|
return (tail(a)() < tail(b)());
|
|
}
|
|
template <class T>
|
|
bool operator<( const odd_list<T>&, a_unique_type_for_nil ) {
|
|
return false;
|
|
}
|
|
template <class T>
|
|
bool operator<( const list<T>&, a_unique_type_for_nil ) {
|
|
return false;
|
|
}
|
|
template <class T>
|
|
bool operator<( a_unique_type_for_nil, const odd_list<T>& b ) {
|
|
return !null(b)();
|
|
}
|
|
template <class T>
|
|
bool operator<( a_unique_type_for_nil, const list<T>& b ) {
|
|
return !null(b)();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Implement cat and cons after the list types are defined.
|
|
//////////////////////////////////////////////////////////////////////
|
|
namespace impl {
|
|
using listlike::ListLike;
|
|
|
|
template <class T, class F, class L>
|
|
struct ConsHelp2<T,F,L,true>
|
|
{
|
|
typedef typename boost::remove_reference<T>::type TT;
|
|
typedef typename L::force_result_type type;
|
|
static type go( const TT& x, const F& f ) {
|
|
return type( x, f );
|
|
}
|
|
};
|
|
template <class T, class F>
|
|
struct ConsHelp2<T,F,list<T>,true>
|
|
{
|
|
typedef typename boost::remove_reference<T>::type TT;
|
|
typedef list<TT> L;
|
|
typedef typename L::force_result_type type;
|
|
static type go( const TT& x, const F& f ) {
|
|
return odd_list<TT>(x, list<TT>(
|
|
boost::intrusive_ptr<Cache<TT> >(new Cache<T>(
|
|
typename Cache<TT>::CvtFxn(),f))));
|
|
}
|
|
};
|
|
template <class T, class F>
|
|
struct ConsHelp2<T,F,odd_list<T>,true>
|
|
{
|
|
typedef typename boost::remove_reference<T>::type TT;
|
|
typedef odd_list<TT> L;
|
|
typedef typename L::force_result_type type;
|
|
static type go( const TT& x, const F& f ) {
|
|
return odd_list<TT>(x, list<TT>( ListRaw(), new Cache<T>(f) ));
|
|
}
|
|
};
|
|
template <class T, class F>
|
|
struct ConsHelp2<T,F,a_unique_type_for_nil,false>
|
|
{
|
|
typedef typename boost::remove_reference<T>::type TT;
|
|
typedef odd_list<TT> type;
|
|
static type go( const TT& x, const F& f ) {
|
|
return odd_list<TT>(x, list<TT>( ListRaw(), new Cache<T>(f) ));
|
|
}
|
|
};
|
|
|
|
template <class T, class L, bool b> struct ConsHelp1 {
|
|
typedef typename boost::remove_reference<T>::type TT;
|
|
typedef typename L::force_result_type type;
|
|
static type go( const TT& x, const L& l ) {
|
|
return type(x,l);
|
|
}
|
|
};
|
|
template <class T> struct ConsHelp1<T,a_unique_type_for_nil,false> {
|
|
typedef typename boost::remove_reference<T>::type TT;
|
|
typedef odd_list<TT> type;
|
|
static type go( const TT& x, const a_unique_type_for_nil& n ) {
|
|
return type(x,n);
|
|
}
|
|
};
|
|
template <class T, class F> struct ConsHelp1<T,F,false> {
|
|
// It's a function returning a list
|
|
// This is the one I have not fixed yet....
|
|
// typedef typename F::result_type L;
|
|
// typedef typename result_of::template ListType<F>::result_type L;
|
|
typedef odd_list<T> L;
|
|
typedef ConsHelp2<T,F,L,boost::is_base_and_derived<ListLike,L>::value> help;
|
|
typedef typename help::type type;
|
|
static type go( const T& x, const F& f ) {
|
|
return help::go(x,f);
|
|
}
|
|
};
|
|
|
|
template <class T, class L, bool b>
|
|
struct ConsHelp0;
|
|
|
|
template <class T>
|
|
struct ConsHelp0<T,a_unique_type_for_nil,true> {
|
|
typedef typename boost::remove_reference<T>::type TT;
|
|
typedef odd_list<T> type;
|
|
};
|
|
|
|
template <class T>
|
|
struct ConsHelp0<const T &,const a_unique_type_for_nil &,true> {
|
|
typedef typename boost::remove_reference<T>::type TT;
|
|
typedef odd_list<TT> type;
|
|
};
|
|
|
|
template <class T>
|
|
struct ConsHelp0<T &,a_unique_type_for_nil &,true> {
|
|
typedef typename boost::remove_reference<T>::type TT;
|
|
typedef odd_list<TT> type;
|
|
};
|
|
|
|
template <class T, class L>
|
|
struct ConsHelp0<T,L,false> {
|
|
// This removes any references from L for correct return type
|
|
// identification.
|
|
typedef typename boost::remove_reference<L>::type LType;
|
|
typedef typename ConsHelp1<T,LType,
|
|
boost::is_base_and_derived<ListLike,LType>::value>::type type;
|
|
};
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// cons (t,l) - cons a value to the front of a list.
|
|
// Note: The first arg, t, must be a value.
|
|
// The second arg, l, can be a list or NIL
|
|
// or a function that returns a list.
|
|
/////////////////////////////////////////////////////////////////////
|
|
struct Cons
|
|
{
|
|
/* template <class T, class L> struct sig : public fun_type<
|
|
typename ConsHelp1<T,L,
|
|
boost::is_base_and_derived<ListLike,L>::value>::type> {};
|
|
*/
|
|
template <typename Sig> struct result;
|
|
|
|
template <typename This, typename T, typename L>
|
|
struct result<This(T, L)>
|
|
{
|
|
typedef typename ConsHelp0<T,L,
|
|
listlike::detect_nil<L>::is_nil>::type type;
|
|
};
|
|
|
|
template <typename This, typename T>
|
|
struct result<This(T,a_unique_type_for_nil)>
|
|
{
|
|
typedef typename boost::remove_reference<T>::type TT;
|
|
typedef odd_list<TT> type;
|
|
};
|
|
|
|
template <typename T, typename L>
|
|
typename result<Cons(T,L)>::type
|
|
operator()( const T& x, const L& l ) const {
|
|
typedef typename result_of::ListType<L>::LType LType;
|
|
typedef ConsHelp1<T,LType,
|
|
boost::is_base_and_derived<ListLike,LType>::value> help;
|
|
return help::go(x,l);
|
|
}
|
|
|
|
template <typename T>
|
|
typename result<Cons(T,a_unique_type_for_nil)>::type
|
|
operator()( const T& x, const a_unique_type_for_nil &n ) const {
|
|
typedef typename result<Cons(T,a_unique_type_for_nil)>::type LL;
|
|
typedef ConsHelp1<T,LL,
|
|
boost::is_base_and_derived<ListLike,LL>::value> help;
|
|
return help::go(x,n);
|
|
}
|
|
|
|
};
|
|
}
|
|
|
|
typedef boost::phoenix::function<impl::Cons> Cons;
|
|
Cons cons;
|
|
|
|
namespace impl {
|
|
|
|
template <class L, class M, bool b>
|
|
struct CatHelp0;
|
|
|
|
template <class LL>
|
|
struct CatHelp0<LL,a_unique_type_for_nil,true> {
|
|
typedef typename result_of::template ListType<LL>::LType type;
|
|
};
|
|
|
|
template <class LL>
|
|
struct CatHelp0<const LL &,const a_unique_type_for_nil &,true> {
|
|
typedef typename result_of::template ListType<LL>::LType type;
|
|
//typedef L type;
|
|
};
|
|
|
|
template <class LL>
|
|
struct CatHelp0<LL &,a_unique_type_for_nil &,true> {
|
|
typedef typename result_of::template ListType<LL>::LType type;
|
|
//typedef L type;
|
|
};
|
|
|
|
template <class LL, class MM>
|
|
struct CatHelp0<LL,MM,false> {
|
|
// This removes any references from L for correct return type
|
|
// identification.
|
|
typedef typename result_of::template ListType<LL>::LType type;
|
|
// typedef typename ConsHelp1<T,LType,
|
|
// boost::is_base_and_derived<ListLike,LType>::value>::type type;
|
|
};
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// cat (l,m) - concatenate lists.
|
|
// Note: The first arg, l, must be a list or NIL.
|
|
// The second arg, m, can be a list or NIL
|
|
// or a function that returns a list.
|
|
/////////////////////////////////////////////////////////////////////
|
|
struct Cat
|
|
{
|
|
template <class L, class M, bool b, class R>
|
|
struct Helper /*: public c_fun_type<L,M,R>*/ {
|
|
template <typename Sig> struct result;
|
|
|
|
template <typename This>
|
|
struct result<This(L,M)>
|
|
{
|
|
typedef typename result_of::ListType<L>::tail_result_type type;
|
|
};
|
|
|
|
typedef R return_type;
|
|
R operator()( const L& l, const M& m,
|
|
reuser2<INV,VAR,INV,Helper,
|
|
typename result_of::template ListType<L>::tail_result_type,M>
|
|
r = NIL ) const {
|
|
if( null(l)() )
|
|
return m().force();
|
|
else
|
|
return cons( head(l)(), r( Helper<L,M,b,R>(), tail(l), m )() );
|
|
}
|
|
};
|
|
template <class L, class M, class R>
|
|
struct Helper<L,M,true,R> /*: public c_fun_type<L,M,R>*/ {
|
|
template <typename Sig> struct result;
|
|
|
|
template <typename This>
|
|
struct result<This(L,M)>
|
|
{
|
|
typedef typename result_of::ListType<L>::tail_result_type type;
|
|
};
|
|
typedef R return_type;
|
|
R operator()( const L& l, const M& m,
|
|
reuser2<INV,VAR,INV,Helper,
|
|
typename result_of::template ListType<L>::tail_result_type,M>
|
|
r = NIL ) const {
|
|
if( null(l)() )
|
|
return m.force();
|
|
else
|
|
return cons( head(l)(), r(Helper<L,M,true,R>(), tail(l), m )());
|
|
}
|
|
};
|
|
template <class L, class R>
|
|
struct Helper<L,a_unique_type_for_nil,false,R>
|
|
/*: public c_fun_type<L,
|
|
a_unique_type_for_nil,odd_list<typename L::value_type> > */
|
|
{
|
|
typedef odd_list<typename result_of::template ListType<L>::value_type> type;
|
|
odd_list<typename result_of::template ListType<L>::value_type>
|
|
operator()( const L& l, const a_unique_type_for_nil& ) const {
|
|
return l;
|
|
}
|
|
};
|
|
public:
|
|
/*template <class L, class M> struct sig : public fun_type<
|
|
typename RT<cons_type,typename L::value_type,M>::result_type>
|
|
{}; */
|
|
// Need to work out the return type here.
|
|
template <typename Sig> struct result;
|
|
|
|
template <typename This, typename L, typename M>
|
|
struct result<This(L,M)>
|
|
{
|
|
typedef typename CatHelp0<L,M,
|
|
listlike::detect_nil<M>::is_nil>::type type;
|
|
// typedef typename result_of::ListType<L>::tail_result_type type;
|
|
};
|
|
|
|
template <typename This, typename L>
|
|
struct result<This(L,a_unique_type_for_nil)>
|
|
{
|
|
typedef typename result_of::ListType<L>::tail_result_type type;
|
|
};
|
|
template <class L, class M>
|
|
typename result<Cat(L,M)>::type operator()( const L& l, const M& m ) const
|
|
{
|
|
listlike::EnsureListLike<L>();
|
|
return Helper<L,M,
|
|
boost::is_base_and_derived<typename listlike::ListLike,M>::value,
|
|
typename result<Cat(L,M)>::type>()(l,m);
|
|
}
|
|
|
|
template <class L>
|
|
typename result<Cat(L,a_unique_type_for_nil)>::type operator()( const L& l, const a_unique_type_for_nil& /* n */ ) const
|
|
{
|
|
listlike::EnsureListLike<L>();
|
|
return l;
|
|
}
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
typedef boost::phoenix::function<impl::Cat> Cat;
|
|
Cat cat;
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Handy functions for making list literals
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Yes, these aren't functoids, they're just template functions. I'm
|
|
// lazy and created these mostly to make it easily to make little lists
|
|
// in the sample code snippets that appear in papers.
|
|
|
|
struct UseList {
|
|
template <class T> struct List { typedef list<T> type; };
|
|
};
|
|
struct UseOddList {
|
|
template <class T> struct List { typedef odd_list<T> type; };
|
|
};
|
|
struct UseStrictList {
|
|
template <class T> struct List { typedef strict_list<T> type; };
|
|
};
|
|
|
|
template <class Kind = UseList>
|
|
struct list_with {
|
|
template <class T>
|
|
typename Kind::template List<T>::type
|
|
operator()( const T& a ) const {
|
|
typename Kind::template List<T>::type l;
|
|
l = cons( a, l );
|
|
return l;
|
|
}
|
|
|
|
template <class T>
|
|
typename Kind::template List<T>::type
|
|
operator()( const T& a, const T& b ) const {
|
|
typename Kind::template List<T>::type l;
|
|
l = cons( b, l );
|
|
l = cons( a, l );
|
|
return l;
|
|
}
|
|
|
|
template <class T>
|
|
typename Kind::template List<T>::type
|
|
operator()( const T& a, const T& b, const T& c ) const {
|
|
typename Kind::template List<T>::type l;
|
|
l = cons( c, l );
|
|
l = cons( b, l );
|
|
l = cons( a, l );
|
|
return l;
|
|
}
|
|
|
|
template <class T>
|
|
typename Kind::template List<T>::type
|
|
operator()( const T& a, const T& b, const T& c, const T& d ) const {
|
|
typename Kind::template List<T>::type l;
|
|
l = cons( d, l );
|
|
l = cons( c, l );
|
|
l = cons( b, l );
|
|
l = cons( a, l );
|
|
return l;
|
|
}
|
|
|
|
template <class T>
|
|
typename Kind::template List<T>::type
|
|
operator()( const T& a, const T& b, const T& c, const T& d,
|
|
const T& e ) const {
|
|
typename Kind::template List<T>::type l;
|
|
l = cons( e, l );
|
|
l = cons( d, l );
|
|
l = cons( c, l );
|
|
l = cons( b, l );
|
|
l = cons( a, l );
|
|
return l;
|
|
}
|
|
};
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|