/*=============================================================================
    Phoenix V1.0
    Copyright (c) 2001-2002 Joel de Guzman

    Permission to copy, use, modify, sell and distribute this software
    is granted provided this copyright notice appears in all copies.
    This software is provided "as is" without express or implied
    warranty, and with no claim as to its suitability for any purpose.
==============================================================================*/
#ifndef PHOENIX_OPERATORS_HPP
#define PHOENIX_OPERATORS_HPP

///////////////////////////////////////////////////////////////////////////////
#if !defined(BOOST_NO_CWCTYPE)
    #include <cwctype>
#endif

#if defined(__BORLANDC__) || (defined(__ICL) && __ICL >= 700)
#define CREF const&
#else
#define CREF
#endif

#include "boost/spirit/phoenix/actor.hpp"
#include "boost/spirit/phoenix/composite.hpp"
#include "boost/config.hpp"

///////////////////////////////////////////////////////////////////////////////
namespace phoenix {

///////////////////////////////////////////////////////////////////////////////
//
//  Operators
//
//      Lazy operators
//
//      This class provides a mechanism for lazily evaluating operators.
//      Syntactically, a lazy operator looks like an ordinary C/C++
//      infix, prefix or postfix operator. The operator application
//      looks the same. However, unlike ordinary operators, the actual
//      operator execution is deferred. (see actor.hpp, primitives.hpp
//      and composite.hpp for an overview). Samples:
//
//          arg1 + arg2
//          1 + arg1 * arg2
//          1 / -arg1
//          arg1 < 150
//
//      T1 set of classes implement all the C++ free operators. Like
//      lazy functions (see functions.hpp), lazy operators are not
//      immediately executed when invoked. Instead, a composite (see
//      composite.hpp) object is created and returned to the caller.
//      Example:
//
//          (arg1 + arg2) * arg3
//
//      does nothing more than return a composite. T1 second function
//      call will evaluate the actual operators. Example:
//
//          int i = 4, j = 5, k = 6;
//          cout << ((arg1 + arg2) * arg3)(i, j, k);
//
//      will print out "54".
//
//      Arbitrarily complex expressions can be lazily evaluated
//      following three simple rules:
//
//          1) Lazy evaluated binary operators apply when at least one
//          of the operands is an actor object (see actor.hpp and
//          primitives.hpp). Consequently, if an operand is not an actor
//          object, it is implicitly converted to an object of type
//          actor<value<T> > (where T is the original type of the
//          operand).
//
//          2) Lazy evaluated unary operators apply only to operands
//          which are actor objects.
//
//          3) The result of a lazy operator is a composite actor object
//          that can in turn apply to rule 1.
//
//      Example:
//
//          arg1 + 3
//
//      is a lazy expression involving the operator+. Following rule 1,
//      lazy evaluation is triggered since arg1 is an instance of an
//      actor<argument<N> > class (see primitives.hpp). The right
//      operand <3> is implicitly converted to an actor<value<int> >.
//      The result of this binary + expression is a composite object,
//      following rule 3.
//
//      Take note that although at least one of the operands must be a
//      valid actor class in order for lazy evaluation to take effect,
//      if this is not the case and we still want to lazily evaluate an
//      expression, we can use var(x), val(x) or cref(x) to transform
//      the operand into a valid action object (see primitives.hpp).
//      Example:
//
//          val(1) << 3;
//
//      Supported operators:
//
//          Unary operators:
//
//              prefix:   ~, !, -, +, ++, --, & (reference), * (dereference)
//              postfix:  ++, --
//
//          Binary operators:
//
//              =, [], +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=
//              +, -, *, /, %, &, |, ^, <<, >>
//              ==, !=, <, >, <=, >=
//              &&, ||
//
//      Each operator has a special tag type associated with it. For
//      example the binary + operator has a plus_op tag type associated
//      with it. This is used to specialize either the unary_operator or
//      binary_operator template classes (see unary_operator and
//      binary_operator below). Specializations of these unary_operator
//      and binary_operator are the actual workhorses that implement the
//      operations. The behavior of each lazy operator depends on these
//      unary_operator and binary_operator specializations. 'preset'
//      specializations conform to the canonical operator rules modeled
//      by the behavior of integers and pointers:
//
//          Prefix -, + and ~ accept constant arguments and return an
//          object by value.
//
//          The ! accept constant arguments and returns a boolean
//          result.
//
//          The & (address-of), * (dereference) both return a reference
//          to an object.
//
//          Prefix ++ returns a reference to its mutable argument after
//          it is incremented.
//
//          Postfix ++ returns the mutable argument by value before it
//          is incremented.
//
//          The += and its family accept mutable right hand side (rhs)
//          operand and return a reference to the rhs operand.
//
//          Infix + and its family accept constant arguments and return
//          an object by value.
//
//          The == and its family accept constant arguments and return a
//          boolean result.
//
//          Operators && and || accept constant arguments and return a
//          boolean result and are short circuit evaluated as expected.
//
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
//
//  Operator tags
//
//      Each C++ operator has a corresponding tag type. This is
//      used as a means for specializing the unary_operator and
//      binary_operator (see below). The tag also serves as the
//      lazy operator type compatible as a composite operation
//      see (composite.hpp).
//
///////////////////////////////////////////////////////////////////////////////

//  Unary operator tags

struct negative_op;         struct positive_op;
struct logical_not_op;      struct invert_op;
struct reference_op;        struct dereference_op;
struct pre_incr_op;         struct pre_decr_op;
struct post_incr_op;        struct post_decr_op;

//  Binary operator tags

struct assign_op;           struct index_op;
struct plus_assign_op;      struct minus_assign_op;
struct times_assign_op;     struct divide_assign_op;    struct mod_assign_op;
struct and_assign_op;       struct or_assign_op;        struct xor_assign_op;
struct shift_l_assign_op;   struct shift_r_assign_op;

struct plus_op;             struct minus_op;
struct times_op;            struct divide_op;           struct mod_op;
struct and_op;              struct or_op;               struct xor_op;
struct shift_l_op;          struct shift_r_op;

struct eq_op;               struct not_eq_op;
struct lt_op;               struct lt_eq_op;
struct gt_op;               struct gt_eq_op;
struct logical_and_op;      struct logical_or_op;

///////////////////////////////////////////////////////////////////////////////
//
//  unary_operator<TagT, T>
//
//      The unary_operator class implements most of the C++ unary
//      operators. Each specialization is basically a simple static eval
//      function plus a result_type typedef that determines the return
//      type of the eval function.
//
//      TagT is one of the unary operator tags above and T is the data
//      type (argument) involved in the operation.
//
//      Only the behavior of C/C++ built-in types are taken into account
//      in the specializations provided below. For user-defined types,
//      these specializations may still be used provided that the
//      operator overloads of such types adhere to the standard behavior
//      of built-in types.
//
//      T1 separate special_ops.hpp file implements more stl savvy
//      specializations. Other more specialized unary_operator
//      implementations may be defined by the client for specific
//      unary operator tags/data types.
//
///////////////////////////////////////////////////////////////////////////////
template <typename TagT, typename T>
struct unary_operator;

//////////////////////////////////
template <typename T>
struct unary_operator<negative_op, T> {

    typedef T const result_type;
    static result_type eval(T const& v)
    { return -v; }
};

//////////////////////////////////
template <typename T>
struct unary_operator<positive_op, T> {

    typedef T const result_type;
    static result_type eval(T const& v)
    { return +v; }
};

//////////////////////////////////
template <typename T>
struct unary_operator<logical_not_op, T> {

    typedef bool result_type;
    static result_type eval(T const& v)
    { return !v; }
};

//////////////////////////////////
template <typename T>
struct unary_operator<invert_op, T> {

    typedef T const result_type;
    static result_type eval(T const& v)
    { return ~v; }
};

//////////////////////////////////
template <typename T>
struct unary_operator<reference_op, T> {

    typedef T* result_type;
    static result_type eval(T& v)
    { return &v; }
};

//////////////////////////////////
template <typename T>
struct unary_operator<dereference_op, T*> {

    typedef T& result_type;
    static result_type eval(T* v)
    { return *v; }
};

//////////////////////////////////
template <typename T>
struct unary_operator<dereference_op, T* const> {

    typedef T& result_type;
    static result_type eval(T* const v)
    { return *v; }
};

//////////////////////////////////
template <>
struct unary_operator<dereference_op, nil_t> {

    //  G++ eager template instantiation
    //  somehow requires this.
    typedef nil_t result_type;
};

//////////////////////////////////
#ifndef __BORLANDC__
template <>
struct unary_operator<dereference_op, nil_t const> {

    //  G++ eager template instantiation
    //  somehow requires this.
    typedef nil_t result_type;
};
#endif

//////////////////////////////////
template <typename T>
struct unary_operator<pre_incr_op, T> {

    typedef T& result_type;
    static result_type eval(T& v)
    { return ++v; }
};

//////////////////////////////////
template <typename T>
struct unary_operator<pre_decr_op, T> {

    typedef T& result_type;
    static result_type eval(T& v)
    { return --v; }
};

//////////////////////////////////
template <typename T>
struct unary_operator<post_incr_op, T> {

    typedef T const result_type;
    static result_type eval(T& v)
    { T t(v); ++v; return t; }
};

//////////////////////////////////
template <typename T>
struct unary_operator<post_decr_op, T> {

    typedef T const result_type;
    static result_type eval(T& v)
    { T t(v); --v; return t; }
};

///////////////////////////////////////////////////////////////////////////////
//
//  rank<T>
//
//      rank<T> class has a static int constant 'value' that defines the
//      absolute rank of a type. rank<T> is used to choose the result
//      type of binary operators such as +. The type with the higher
//      rank wins and is used as the operator's return type. T1 generic
//      user defined type has a very high rank and always wins when
//      compared against a user defined type. If this is not desireable,
//      one can write a rank specialization for the type.
//
//      Take note that ranks 0..9999 are reserved for the framework.
//
///////////////////////////////////////////////////////////////////////////////
template <typename T>
struct rank { static int const value = INT_MAX; };

template <> struct rank<void>               { static int const value = 0; };
template <> struct rank<bool>               { static int const value = 10; };

template <> struct rank<char>               { static int const value = 20; };
template <> struct rank<signed char>        { static int const value = 20; };
template <> struct rank<unsigned char>      { static int const value = 30; };
#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
template <> struct rank<wchar_t>            { static int const value = 40; };
#endif // !defined(BOOST_NO_INTRINSIC_WCHAR_T)

template <> struct rank<short>              { static int const value = 50; };
template <> struct rank<unsigned short>     { static int const value = 60; };

template <> struct rank<int>                { static int const value = 70; };
template <> struct rank<unsigned int>       { static int const value = 80; };

template <> struct rank<long>               { static int const value = 90; };
template <> struct rank<unsigned long>      { static int const value = 100; };

#ifdef BOOST_HAS_LONG_LONG
template <> struct rank<long long>          { static int const value = 110; };
template <> struct rank<unsigned long long> { static int const value = 120; };
#endif

template <> struct rank<float>              { static int const value = 130; };
template <> struct rank<double>             { static int const value = 140; };
template <> struct rank<long double>        { static int const value = 150; };

template <typename T> struct rank<T*>
{ static int const value = 160; };

template <typename T> struct rank<T* const>
{ static int const value = 160; };

template <typename T, int N> struct rank<T[N]>
{ static int const value = 160; };

///////////////////////////////////////////////////////////////////////////////
//
//  higher_rank<T0, T1>
//
//      Chooses the type (T0 or T1) with the higher rank.
//
///////////////////////////////////////////////////////////////////////////////
template <typename T0, typename T1>
struct higher_rank {

    enum {

        rank1 = rank<T0>::value,
        rank2 = rank<T1>::value,

#if defined __BORLANDC__ && __BORLANDC__ >= 0x561
        siz = (rank<T0>::value < rank<T1>::value) ? 1 : 2
#else
        siz = (rank1 < rank2) ? 1 : 2
#endif
    };

    typedef char compare_rank[siz];
    typedef typename impl::if_t<compare_rank, T1, T0>::type type;
};

///////////////////////////////////////////////////////////////////////////////
//
//  binary_operator<TagT, T0, T1>
//
//      The binary_operator class implements most of the C++ binary
//      operators. Each specialization is basically a simple static eval
//      function plus a result_type typedef that determines the return
//      type of the eval function.
//
//      TagT is one of the binary operator tags above T0 and T1 are the
//      (arguments') data types involved in the operation.
//
//      Only the behavior of C/C++ built-in types are taken into account
//      in the specializations provided below. For user-defined types,
//      these specializations may still be used provided that the
//      operator overloads of such types adhere to the standard behavior
//      of built-in types.
//
//      T1 separate special_ops.hpp file implements more stl savvy
//      specializations. Other more specialized unary_operator
//      implementations may be defined by the client for specific
//      unary operator tags/data types.
//
//      All binary_operator except the logical_and_op and logical_or_op
//      have an eval static function that carries out the actual operation.
//      The logical_and_op and logical_or_op d are special because these
//      two operators are short-circuit evaluated.
//
///////////////////////////////////////////////////////////////////////////////
template <typename TagT, typename T0, typename T1>
struct binary_operator;

//////////////////////////////////
template <typename T0, typename T1>
struct binary_operator<assign_op, T0, T1> {

    typedef T0& result_type;
    static result_type eval(T0& lhs, T1 const& rhs)
    { return lhs = rhs; }
};

//////////////////////////////////
template <typename T1>
struct binary_operator<index_op, nil_t, T1> {

    //  G++ eager template instantiation
    //  somehow requires this.
    typedef nil_t result_type;
};

//////////////////////////////////
template <typename T0, typename T1>
struct binary_operator<index_op, T0*, T1> {

    typedef T0& result_type;
    static result_type eval(T0* ptr, T1 const& index)
    { return ptr[index]; }
};

//////////////////////////////////
template <typename T0, typename T1>
struct binary_operator<index_op, T0* const, T1> {

    typedef T0& result_type;
    static result_type eval(T0* const ptr, T1 const& index)
    { return ptr[index]; }
};

//////////////////////////////////
template <typename T0, int N, typename T1>
struct binary_operator<index_op, T0[N], T1> {

    typedef T0& result_type;
    static result_type eval(T0* ptr, T1 const& index)
    { return ptr[index]; }
};

//////////////////////////////////
template <typename T0, typename T1>
struct binary_operator<plus_assign_op, T0, T1> {

    typedef T0& result_type;
    static result_type eval(T0& lhs, T1 const& rhs)
    { return lhs += rhs; }
};

//////////////////////////////////
template <typename T0, typename T1>
struct binary_operator<minus_assign_op, T0, T1> {

    typedef T0& result_type;
    static result_type eval(T0& lhs, T1 const& rhs)
    { return lhs -= rhs; }
};

//////////////////////////////////
template <typename T0, typename T1>
struct binary_operator<times_assign_op, T0, T1> {

    typedef T0& result_type;
    static result_type eval(T0& lhs, T1 const& rhs)
    { return lhs *= rhs; }
};

//////////////////////////////////
template <typename T0, typename T1>
struct binary_operator<divide_assign_op, T0, T1> {

    typedef T0& result_type;
    static result_type eval(T0& lhs, T1 const& rhs)
    { return lhs /= rhs; }
};

//////////////////////////////////
template <typename T0, typename T1>
struct binary_operator<mod_assign_op, T0, T1> {

    typedef T0& result_type;
    static result_type eval(T0& lhs, T1 const& rhs)
    { return lhs %= rhs; }
};

//////////////////////////////////
template <typename T0, typename T1>
struct binary_operator<and_assign_op, T0, T1> {

    typedef T0& result_type;
    static result_type eval(T0& lhs, T1 const& rhs)
    { return lhs &= rhs; }
};

//////////////////////////////////
template <typename T0, typename T1>
struct binary_operator<or_assign_op, T0, T1> {

    typedef T0& result_type;
    static result_type eval(T0& lhs, T1 const& rhs)
    { return lhs |= rhs; }
};

//////////////////////////////////
template <typename T0, typename T1>
struct binary_operator<xor_assign_op, T0, T1> {

    typedef T0& result_type;
    static result_type eval(T0& lhs, T1 const& rhs)
    { return lhs ^= rhs; }
};

//////////////////////////////////
template <typename T0, typename T1>
struct binary_operator<shift_l_assign_op, T0, T1> {

    typedef T0& result_type;
    static result_type eval(T0& lhs, T1 const& rhs)
    { return lhs <<= rhs; }
};

//////////////////////////////////
template <typename T0, typename T1>
struct binary_operator<shift_r_assign_op, T0, T1> {

    typedef T0& result_type;
    static result_type eval(T0& lhs, T1 const& rhs)
    { return lhs >>= rhs; }
};

//////////////////////////////////
template <typename T0, typename T1>
struct binary_operator<plus_op, T0, T1> {

    typedef typename higher_rank<T0, T1>::type const result_type;
    static result_type eval(T0 const& lhs, T1 const& rhs)
    { return lhs + rhs; }
};

//////////////////////////////////
template <typename T0, typename T1>
struct binary_operator<minus_op, T0, T1> {

    typedef typename higher_rank<T0, T1>::type const result_type;
    static result_type eval(T0 const& lhs, T1 const& rhs)
    { return lhs - rhs; }
};

//////////////////////////////////
template <typename T0, typename T1>
struct binary_operator<times_op, T0, T1> {

    typedef typename higher_rank<T0, T1>::type const result_type;
    static result_type eval(T0 const& lhs, T1 const& rhs)
    { return lhs * rhs; }
};

//////////////////////////////////
template <typename T0, typename T1>
struct binary_operator<divide_op, T0, T1> {

    typedef typename higher_rank<T0, T1>::type const result_type;
    static result_type eval(T0 const& lhs, T1 const& rhs)
    { return lhs / rhs; }
};

//////////////////////////////////
template <typename T0, typename T1>
struct binary_operator<mod_op, T0, T1> {

    typedef typename higher_rank<T0, T1>::type const result_type;
    static result_type eval(T0 const& lhs, T1 const& rhs)
    { return lhs % rhs; }
};

//////////////////////////////////
template <typename T0, typename T1>
struct binary_operator<and_op, T0, T1> {

    typedef typename higher_rank<T0, T1>::type const result_type;
    static result_type eval(T0 const& lhs, T1 const& rhs)
    { return lhs & rhs; }
};

//////////////////////////////////
template <typename T0, typename T1>
struct binary_operator<or_op, T0, T1> {

    typedef typename higher_rank<T0, T1>::type const result_type;
    static result_type eval(T0 const& lhs, T1 const& rhs)
    { return lhs | rhs; }
};

//////////////////////////////////
template <typename T0, typename T1>
struct binary_operator<xor_op, T0, T1> {

    typedef typename higher_rank<T0, T1>::type const result_type;
    static result_type eval(T0 const& lhs, T1 const& rhs)
    { return lhs ^ rhs; }
};

//////////////////////////////////
template <typename T0, typename T1>
struct binary_operator<shift_l_op, T0, T1> {

    typedef T0 const result_type;
    static result_type eval(T0 const& lhs, T1 const& rhs)
    { return lhs << rhs; }
};

//////////////////////////////////
template <typename T0, typename T1>
struct binary_operator<shift_r_op, T0, T1> {

    typedef T0 const result_type;
    static result_type eval(T0 const& lhs, T1 const& rhs)
    { return lhs >> rhs; }
};

//////////////////////////////////
template <typename T0, typename T1>
struct binary_operator<eq_op, T0, T1> {

    typedef bool result_type;
    static result_type eval(T0 const& lhs, T1 const& rhs)
    { return lhs == rhs; }
};

//////////////////////////////////
template <typename T0, typename T1>
struct binary_operator<not_eq_op, T0, T1> {

    typedef bool result_type;
    static result_type eval(T0 const& lhs, T1 const& rhs)
    { return lhs != rhs; }
};

//////////////////////////////////
template <typename T0, typename T1>
struct binary_operator<lt_op, T0, T1> {

    typedef bool result_type;
    static result_type eval(T0 const& lhs, T1 const& rhs)
    { return lhs < rhs; }
};

//////////////////////////////////
template <typename T0, typename T1>
struct binary_operator<lt_eq_op, T0, T1> {

    typedef bool result_type;
    static result_type eval(T0 const& lhs, T1 const& rhs)
    { return lhs <= rhs; }
};

//////////////////////////////////
template <typename T0, typename T1>
struct binary_operator<gt_op, T0, T1> {

    typedef bool result_type;
    static result_type eval(T0 const& lhs, T1 const& rhs)
    { return lhs > rhs; }
};

//////////////////////////////////
template <typename T0, typename T1>
struct binary_operator<gt_eq_op, T0, T1> {

    typedef bool result_type;
    static result_type eval(T0 const& lhs, T1 const& rhs)
    { return lhs >= rhs; }
};

//////////////////////////////////
template <typename T0, typename T1>
struct binary_operator<logical_and_op, T0, T1> {

    typedef bool result_type;
    //  no eval function, see comment above.
};

//////////////////////////////////
template <typename T0, typename T1>
struct binary_operator<logical_or_op, T0, T1> {

    typedef bool result_type;
    //  no eval function, see comment above.
};

///////////////////////////////////////////////////////////////////////////////
//
//  negative lazy operator (prefix -)
//
///////////////////////////////////////////////////////////////////////////////
struct negative_op {

    template <typename T0>
    struct result {

        typedef typename unary_operator<negative_op, T0>::result_type type;
    };

    template <typename T0>
    typename unary_operator<negative_op, T0>::result_type
    operator()(T0& _0) const
    { return unary_operator<negative_op, T0>::eval(_0); }
};

//////////////////////////////////
template <typename BaseT>
inline typename impl::make_unary<negative_op, BaseT>::type
operator-(actor<BaseT> const& _0)
{
    return impl::make_unary<negative_op, BaseT>::construct(_0);
}

///////////////////////////////////////////////////////////////////////////////
//
//  positive lazy operator (prefix +)
//
///////////////////////////////////////////////////////////////////////////////
struct positive_op {

    template <typename T0>
    struct result {

        typedef typename unary_operator<positive_op, T0>::result_type type;
    };

    template <typename T0>
    typename unary_operator<positive_op, T0>::result_type
    operator()(T0& _0) const
    { return unary_operator<positive_op, T0>::eval(_0); }
};

//////////////////////////////////
template <typename BaseT>
inline typename impl::make_unary<positive_op, BaseT>::type
operator+(actor<BaseT> const& _0)
{
    return impl::make_unary<positive_op, BaseT>::construct(_0);
}

///////////////////////////////////////////////////////////////////////////////
//
//  logical not lazy operator (prefix !)
//
///////////////////////////////////////////////////////////////////////////////
struct logical_not_op {

    template <typename T0>
    struct result {

        typedef typename unary_operator<logical_not_op, T0>::result_type type;
    };

    template <typename T0>
    typename unary_operator<logical_not_op, T0>::result_type
    operator()(T0& _0) const
    { return unary_operator<logical_not_op, T0>::eval(_0); }
};

//////////////////////////////////
template <typename BaseT>
inline typename impl::make_unary<logical_not_op, BaseT>::type
operator!(actor<BaseT> const& _0)
{
    return impl::make_unary<logical_not_op, BaseT>::construct(_0);
}

///////////////////////////////////////////////////////////////////////////////
//
//  invert lazy operator (prefix ~)
//
///////////////////////////////////////////////////////////////////////////////
struct invert_op {

    template <typename T0>
    struct result {

        typedef typename unary_operator<invert_op, T0>::result_type type;
    };

    template <typename T0>
    typename unary_operator<invert_op, T0>::result_type
    operator()(T0& _0) const
    { return unary_operator<invert_op, T0>::eval(_0); }
};

//////////////////////////////////
template <typename BaseT>
inline typename impl::make_unary<invert_op, BaseT>::type
operator~(actor<BaseT> const& _0)
{
    return impl::make_unary<invert_op, BaseT>::construct(_0);
}

///////////////////////////////////////////////////////////////////////////////
//
//  reference lazy operator (prefix &)
//
///////////////////////////////////////////////////////////////////////////////
struct reference_op {

    template <typename T0>
    struct result {

        typedef typename unary_operator<reference_op, T0>::result_type type;
    };

    template <typename T0>
    typename unary_operator<reference_op, T0>::result_type
    operator()(T0& _0) const
    { return unary_operator<reference_op, T0>::eval(_0); }
};

//////////////////////////////////
template <typename BaseT>
inline typename impl::make_unary<reference_op, BaseT>::type
operator&(actor<BaseT> const& _0)
{
    return impl::make_unary<reference_op, BaseT>::construct(_0);
}

///////////////////////////////////////////////////////////////////////////////
//
//  dereference lazy operator (prefix *)
//
///////////////////////////////////////////////////////////////////////////////
struct dereference_op {

    template <typename T0>
    struct result {

        typedef typename unary_operator<dereference_op, T0>::result_type type;
    };

    template <typename T0>
    typename unary_operator<dereference_op, T0>::result_type
    operator()(T0& _0) const
    { return unary_operator<dereference_op, T0>::eval(_0); }
};

//////////////////////////////////
template <typename BaseT>
inline typename impl::make_unary<dereference_op, BaseT>::type
operator*(actor<BaseT> const& _0)
{
    return impl::make_unary<dereference_op, BaseT>::construct(_0);
}

///////////////////////////////////////////////////////////////////////////////
//
//  pre increment lazy operator (prefix ++)
//
///////////////////////////////////////////////////////////////////////////////
struct pre_incr_op {

    template <typename T0>
    struct result {

        typedef typename unary_operator<pre_incr_op, T0>::result_type type;
    };

    template <typename T0>
    typename unary_operator<pre_incr_op, T0>::result_type
    operator()(T0& _0) const
    { return unary_operator<pre_incr_op, T0>::eval(_0); }
};

//////////////////////////////////
template <typename BaseT>
inline typename impl::make_unary<pre_incr_op, BaseT>::type
operator++(actor<BaseT> const& _0)
{
    return impl::make_unary<pre_incr_op, BaseT>::construct(_0);
}

///////////////////////////////////////////////////////////////////////////////
//
//  pre decrement lazy operator (prefix --)
//
///////////////////////////////////////////////////////////////////////////////
struct pre_decr_op {

    template <typename T0>
    struct result {

        typedef typename unary_operator<pre_decr_op, T0>::result_type type;
    };

    template <typename T0>
    typename unary_operator<pre_decr_op, T0>::result_type
    operator()(T0& _0) const
    { return unary_operator<pre_decr_op, T0>::eval(_0); }
};

//////////////////////////////////
template <typename BaseT>
inline typename impl::make_unary<pre_decr_op, BaseT>::type
operator--(actor<BaseT> const& _0)
{
    return impl::make_unary<pre_decr_op, BaseT>::construct(_0);
}

///////////////////////////////////////////////////////////////////////////////
//
//  post increment lazy operator (postfix ++)
//
///////////////////////////////////////////////////////////////////////////////
struct post_incr_op {

    template <typename T0>
    struct result {

        typedef typename unary_operator<post_incr_op, T0>::result_type type;
    };

    template <typename T0>
    typename unary_operator<post_incr_op, T0>::result_type
    operator()(T0& _0) const
    { return unary_operator<post_incr_op, T0>::eval(_0); }
};

//////////////////////////////////
template <typename BaseT>
inline typename impl::make_unary<post_incr_op, BaseT>::type
operator++(actor<BaseT> const& _0, int)
{
    return impl::make_unary<post_incr_op, BaseT>::construct(_0);
}

///////////////////////////////////////////////////////////////////////////////
//
//  post decrement lazy operator (postfix --)
//
///////////////////////////////////////////////////////////////////////////////
struct post_decr_op {

    template <typename T0>
    struct result {

        typedef typename unary_operator<post_decr_op, T0>::result_type type;
    };

    template <typename T0>
    typename unary_operator<post_decr_op, T0>::result_type
    operator()(T0& _0) const
    { return unary_operator<post_decr_op, T0>::eval(_0); }
};

//////////////////////////////////
template <typename BaseT>
inline typename impl::make_unary<post_decr_op, BaseT>::type
operator--(actor<BaseT> const& _0, int)
{
    return impl::make_unary<post_decr_op, BaseT>::construct(_0);
}

///////////////////////////////////////////////////////////////////////////////
//
//  assignment lazy operator (infix =)
//  The acual lazy operator is a member of the actor class.
//
///////////////////////////////////////////////////////////////////////////////
struct assign_op {

    template <typename T0, typename T1>
    struct result {

        typedef typename binary_operator<assign_op, T0, T1>
            ::result_type type;
    };

    template <typename T0, typename T1>
    typename binary_operator<assign_op, T0, T1>::result_type
    operator()(T0& _0, T1& _1) const
    { return binary_operator<assign_op, T0, T1>::eval(_0, _1); }
};

//////////////////////////////////
template <typename BaseT>
template <typename B>
inline typename impl::make_binary1<assign_op, BaseT, B>::type
actor<BaseT>::operator=(B const& _1) const
{
    return impl::make_binary1<assign_op, BaseT, B>::construct(*this, _1);
}

///////////////////////////////////////////////////////////////////////////////
//
//  index lazy operator (array index [])
//  The acual lazy operator is a member of the actor class.
//
///////////////////////////////////////////////////////////////////////////////
struct index_op {

    template <typename T0, typename T1>
    struct result {

        typedef typename binary_operator<index_op, T0, T1>
            ::result_type type;
    };

    template <typename T0, typename T1>
    typename binary_operator<index_op, T0, T1>::result_type
    operator()(T0& _0, T1& _1) const
    { return binary_operator<index_op, T0, T1>::eval(_0, _1); }
};

//////////////////////////////////
template <typename BaseT>
template <typename B>
inline typename impl::make_binary1<index_op, BaseT, B>::type
actor<BaseT>::operator[](B const& _1) const
{
    return impl::make_binary1<index_op, BaseT, B>::construct(*this, _1);
}

///////////////////////////////////////////////////////////////////////////////
//
//  plus assign lazy operator (infix +=)
//
///////////////////////////////////////////////////////////////////////////////
struct plus_assign_op {

    template <typename T0, typename T1>
    struct result {

        typedef typename binary_operator<plus_assign_op, T0, T1>
            ::result_type type;
    };

    template <typename T0, typename T1>
    typename binary_operator<plus_assign_op, T0, T1>::result_type
    operator()(T0& _0, T1& _1) const
    { return binary_operator<plus_assign_op, T0, T1>::eval(_0, _1); }
};

//////////////////////////////////
template <typename BaseT, typename T1>
inline typename impl::make_binary1<plus_assign_op, BaseT, T1>::type
operator+=(actor<BaseT> const& _0, T1 CREF _1)
{
    return impl::make_binary1<plus_assign_op, BaseT, T1>::construct(_0, _1);
}

///////////////////////////////////////////////////////////////////////////////
//
//  minus assign lazy operator (infix -=)
//
///////////////////////////////////////////////////////////////////////////////
struct minus_assign_op {

    template <typename T0, typename T1>
    struct result {

        typedef typename binary_operator<minus_assign_op, T0, T1>
            ::result_type type;
    };

    template <typename T0, typename T1>
    typename binary_operator<minus_assign_op, T0, T1>::result_type
    operator()(T0& _0, T1& _1) const
    { return binary_operator<minus_assign_op, T0, T1>::eval(_0, _1); }
};

//////////////////////////////////
template <typename BaseT, typename T1>
inline typename impl::make_binary1<minus_assign_op, BaseT, T1>::type
operator-=(actor<BaseT> const& _0, T1 CREF _1)
{
    return impl::make_binary1<minus_assign_op, BaseT, T1>::construct(_0, _1);
}

///////////////////////////////////////////////////////////////////////////////
//
//  times assign lazy operator (infix *=)
//
///////////////////////////////////////////////////////////////////////////////
struct times_assign_op {

    template <typename T0, typename T1>
    struct result {

        typedef typename binary_operator<times_assign_op, T0, T1>
            ::result_type type;
    };

    template <typename T0, typename T1>
    typename binary_operator<times_assign_op, T0, T1>::result_type
    operator()(T0& _0, T1& _1) const
    { return binary_operator<times_assign_op, T0, T1>::eval(_0, _1); }
};

//////////////////////////////////
template <typename BaseT, typename T1>
inline typename impl::make_binary1<times_assign_op, BaseT, T1>::type
operator*=(actor<BaseT> const& _0, T1 CREF _1)
{
    return impl::make_binary1<times_assign_op, BaseT, T1>::construct(_0, _1);
}

///////////////////////////////////////////////////////////////////////////////
//
//  divide assign lazy operator (infix /=)
//
///////////////////////////////////////////////////////////////////////////////
struct divide_assign_op {

    template <typename T0, typename T1>
    struct result {

        typedef typename binary_operator<divide_assign_op, T0, T1>
            ::result_type type;
    };

    template <typename T0, typename T1>
    typename binary_operator<divide_assign_op, T0, T1>::result_type
    operator()(T0& _0, T1& _1) const
    { return binary_operator<divide_assign_op, T0, T1>::eval(_0, _1); }
};

//////////////////////////////////
template <typename BaseT, typename T1>
inline typename impl::make_binary1<divide_assign_op, BaseT, T1>::type
operator/=(actor<BaseT> const& _0, T1 CREF _1)
{
    return impl::make_binary1<divide_assign_op, BaseT, T1>::construct(_0, _1);
}

///////////////////////////////////////////////////////////////////////////////
//
//  mod assign lazy operator (infix %=)
//
///////////////////////////////////////////////////////////////////////////////
struct mod_assign_op {

    template <typename T0, typename T1>
    struct result {

        typedef typename binary_operator<mod_assign_op, T0, T1>
            ::result_type type;
    };

    template <typename T0, typename T1>
    typename binary_operator<mod_assign_op, T0, T1>::result_type
    operator()(T0& _0, T1& _1) const
    { return binary_operator<mod_assign_op, T0, T1>::eval(_0, _1); }
};

//////////////////////////////////
template <typename BaseT, typename T1>
inline typename impl::make_binary1<mod_assign_op, BaseT, T1>::type
operator%=(actor<BaseT> const& _0, T1 CREF _1)
{
    return impl::make_binary1<mod_assign_op, BaseT, T1>::construct(_0, _1);
}

///////////////////////////////////////////////////////////////////////////////
//
//  and assign lazy operator (infix &=)
//
///////////////////////////////////////////////////////////////////////////////
struct and_assign_op {

    template <typename T0, typename T1>
    struct result {

        typedef typename binary_operator<and_assign_op, T0, T1>
            ::result_type type;
    };

    template <typename T0, typename T1>
    typename binary_operator<and_assign_op, T0, T1>::result_type
    operator()(T0& _0, T1& _1) const
    { return binary_operator<and_assign_op, T0, T1>::eval(_0, _1); }
};

//////////////////////////////////
template <typename BaseT, typename T1>
inline typename impl::make_binary1<and_assign_op, BaseT, T1>::type
operator&=(actor<BaseT> const& _0, T1 CREF _1)
{
    return impl::make_binary1<and_assign_op, BaseT, T1>::construct(_0, _1);
}

///////////////////////////////////////////////////////////////////////////////
//
//  or assign lazy operator (infix |=)
//
///////////////////////////////////////////////////////////////////////////////
struct or_assign_op {

    template <typename T0, typename T1>
    struct result {

        typedef typename binary_operator<or_assign_op, T0, T1>
            ::result_type type;
    };

    template <typename T0, typename T1>
    typename binary_operator<or_assign_op, T0, T1>::result_type
    operator()(T0& _0, T1& _1) const
    { return binary_operator<or_assign_op, T0, T1>::eval(_0, _1); }
};

//////////////////////////////////
template <typename BaseT, typename T1>
inline typename impl::make_binary1<or_assign_op, BaseT, T1>::type
operator|=(actor<BaseT> const& _0, T1 CREF _1)
{
    return impl::make_binary1<or_assign_op, BaseT, T1>::construct(_0, _1);
}

///////////////////////////////////////////////////////////////////////////////
//
//  xor assign lazy operator (infix ^=)
//
///////////////////////////////////////////////////////////////////////////////
struct xor_assign_op {

    template <typename T0, typename T1>
    struct result {

        typedef typename binary_operator<xor_assign_op, T0, T1>
            ::result_type type;
    };

    template <typename T0, typename T1>
    typename binary_operator<xor_assign_op, T0, T1>::result_type
    operator()(T0& _0, T1& _1) const
    { return binary_operator<xor_assign_op, T0, T1>::eval(_0, _1); }
};

//////////////////////////////////
template <typename BaseT, typename T1>
inline typename impl::make_binary1<xor_assign_op, BaseT, T1>::type
operator^=(actor<BaseT> const& _0, T1 CREF _1)
{
    return impl::make_binary1<xor_assign_op, BaseT, T1>::construct(_0, _1);
}

///////////////////////////////////////////////////////////////////////////////
//
//  shift left assign lazy operator (infix <<=)
//
///////////////////////////////////////////////////////////////////////////////
struct shift_l_assign_op {

    template <typename T0, typename T1>
    struct result {

        typedef typename binary_operator<shift_l_assign_op, T0, T1>
            ::result_type type;
    };

    template <typename T0, typename T1>
    typename binary_operator<shift_l_assign_op, T0, T1>::result_type
    operator()(T0& _0, T1& _1) const
    { return binary_operator<shift_l_assign_op, T0, T1>::eval(_0, _1); }
};

//////////////////////////////////
template <typename BaseT, typename T1>
inline typename impl::make_binary1<shift_l_assign_op, BaseT, T1>::type
operator<<=(actor<BaseT> const& _0, T1 CREF _1)
{
    return impl::make_binary1<shift_l_assign_op, BaseT, T1>::construct(_0, _1);
}

///////////////////////////////////////////////////////////////////////////////
//
//  shift right assign lazy operator (infix >>=)
//
///////////////////////////////////////////////////////////////////////////////
struct shift_r_assign_op {

    template <typename T0, typename T1>
    struct result {

        typedef typename binary_operator<shift_r_assign_op, T0, T1>
            ::result_type type;
    };

    template <typename T0, typename T1>
    typename binary_operator<shift_r_assign_op, T0, T1>::result_type
    operator()(T0& _0, T1& _1) const
    { return binary_operator<shift_r_assign_op, T0, T1>::eval(_0, _1); }
};

//////////////////////////////////
template <typename BaseT, typename T1>
inline typename impl::make_binary1<shift_r_assign_op, BaseT, T1>::type
operator>>=(actor<BaseT> const& _0, T1 CREF _1)
{
    return impl::make_binary1<shift_r_assign_op, BaseT, T1>::construct(_0, _1);
}

///////////////////////////////////////////////////////////////////////////////
//
//  plus lazy operator (infix +)
//
///////////////////////////////////////////////////////////////////////////////
struct plus_op {

    template <typename T0, typename T1>
    struct result {

        typedef typename binary_operator<plus_op, T0, T1>
            ::result_type type;
    };

    template <typename T0, typename T1>
    typename binary_operator<plus_op, T0, T1>::result_type
    operator()(T0& _0, T1& _1) const
    { return binary_operator<plus_op, T0, T1>::eval(_0, _1); }
};

//////////////////////////////////
template <typename BaseT, typename T1>
inline typename impl::make_binary1<plus_op, BaseT, T1>::type
operator+(actor<BaseT> const& _0, T1 CREF _1)
{
    return impl::make_binary1<plus_op, BaseT, T1>::construct(_0, _1);
}

//////////////////////////////////
template <typename T0, typename BaseT>
inline typename impl::make_binary2<plus_op, T0, BaseT>::type
operator+(T0 CREF _0, actor<BaseT> const& _1)
{
    return impl::make_binary2<plus_op, T0, BaseT>::construct(_0, _1);
}

//////////////////////////////////
template <typename BaseT0, typename BaseT1>
inline typename impl::make_binary3<plus_op, BaseT0, BaseT1>::type
operator+(actor<BaseT0> const& _0, actor<BaseT1> const& _1)
{
    return impl::make_binary3<plus_op, BaseT0, BaseT1>::construct(_0, _1);
}

///////////////////////////////////////////////////////////////////////////////
//
//  minus lazy operator (infix -)
//
///////////////////////////////////////////////////////////////////////////////
struct minus_op {

    template <typename T0, typename T1>
    struct result {

        typedef typename binary_operator<minus_op, T0, T1>
            ::result_type type;
    };

    template <typename T0, typename T1>
    typename binary_operator<minus_op, T0, T1>::result_type
    operator()(T0& _0, T1& _1) const
    { return binary_operator<minus_op, T0, T1>::eval(_0, _1); }
};

//////////////////////////////////
template <typename BaseT, typename T1>
inline typename impl::make_binary1<minus_op, BaseT, T1>::type
operator-(actor<BaseT> const& _0, T1 CREF _1)
{
    return impl::make_binary1<minus_op, BaseT, T1>::construct(_0, _1);
}

//////////////////////////////////
template <typename T0, typename BaseT>
inline typename impl::make_binary2<minus_op, T0, BaseT>::type
operator-(T0 CREF _0, actor<BaseT> const& _1)
{
    return impl::make_binary2<minus_op, T0, BaseT>::construct(_0, _1);
}

//////////////////////////////////
template <typename BaseT0, typename BaseT1>
inline typename impl::make_binary3<minus_op, BaseT0, BaseT1>::type
operator-(actor<BaseT0> const& _0, actor<BaseT1> const& _1)
{
    return impl::make_binary3<minus_op, BaseT0, BaseT1>::construct(_0, _1);
}

///////////////////////////////////////////////////////////////////////////////
//
//  times lazy operator (infix *)
//
///////////////////////////////////////////////////////////////////////////////
struct times_op {

    template <typename T0, typename T1>
    struct result {

        typedef typename binary_operator<times_op, T0, T1>
            ::result_type type;
    };

    template <typename T0, typename T1>
    typename binary_operator<times_op, T0, T1>::result_type
    operator()(T0& _0, T1& _1) const
    { return binary_operator<times_op, T0, T1>::eval(_0, _1); }
};

//////////////////////////////////
template <typename BaseT, typename T1>
inline typename impl::make_binary1<times_op, BaseT, T1>::type
operator*(actor<BaseT> const& _0, T1 CREF _1)
{
    return impl::make_binary1<times_op, BaseT, T1>::construct(_0, _1);
}

//////////////////////////////////
template <typename T0, typename BaseT>
inline typename impl::make_binary2<times_op, T0, BaseT>::type
operator*(T0 CREF _0, actor<BaseT> const& _1)
{
    return impl::make_binary2<times_op, T0, BaseT>::construct(_0, _1);
}

//////////////////////////////////
template <typename BaseT0, typename BaseT1>
inline typename impl::make_binary3<times_op, BaseT0, BaseT1>::type
operator*(actor<BaseT0> const& _0, actor<BaseT1> const& _1)
{
    return impl::make_binary3<times_op, BaseT0, BaseT1>::construct(_0, _1);
}

///////////////////////////////////////////////////////////////////////////////
//
//  divide lazy operator (infix /)
//
///////////////////////////////////////////////////////////////////////////////
struct divide_op {

    template <typename T0, typename T1>
    struct result {

        typedef typename binary_operator<divide_op, T0, T1>
            ::result_type type;
    };

    template <typename T0, typename T1>
    typename binary_operator<divide_op, T0, T1>::result_type
    operator()(T0& _0, T1& _1) const
    { return binary_operator<divide_op, T0, T1>::eval(_0, _1); }
};

//////////////////////////////////
template <typename BaseT, typename T1>
inline typename impl::make_binary1<divide_op, BaseT, T1>::type
operator/(actor<BaseT> const& _0, T1 CREF _1)
{
    return impl::make_binary1<divide_op, BaseT, T1>::construct(_0, _1);
}

//////////////////////////////////
template <typename T0, typename BaseT>
inline typename impl::make_binary2<divide_op, T0, BaseT>::type
operator/(T0 CREF _0, actor<BaseT> const& _1)
{
    return impl::make_binary2<divide_op, T0, BaseT>::construct(_0, _1);
}

//////////////////////////////////
template <typename BaseT0, typename BaseT1>
inline typename impl::make_binary3<divide_op, BaseT0, BaseT1>::type
operator/(actor<BaseT0> const& _0, actor<BaseT1> const& _1)
{
    return impl::make_binary3<divide_op, BaseT0, BaseT1>::construct(_0, _1);
}

///////////////////////////////////////////////////////////////////////////////
//
//  mod lazy operator (infix %)
//
///////////////////////////////////////////////////////////////////////////////
struct mod_op {

    template <typename T0, typename T1>
    struct result {

        typedef typename binary_operator<mod_op, T0, T1>
            ::result_type type;
    };

    template <typename T0, typename T1>
    typename binary_operator<mod_op, T0, T1>::result_type
    operator()(T0& _0, T1& _1) const
    { return binary_operator<mod_op, T0, T1>::eval(_0, _1); }
};

//////////////////////////////////
template <typename BaseT, typename T1>
inline typename impl::make_binary1<mod_op, BaseT, T1>::type
operator%(actor<BaseT> const& _0, T1 CREF _1)
{
    return impl::make_binary1<mod_op, BaseT, T1>::construct(_0, _1);
}

//////////////////////////////////
template <typename T0, typename BaseT>
inline typename impl::make_binary2<mod_op, T0, BaseT>::type
operator%(T0 CREF _0, actor<BaseT> const& _1)
{
    return impl::make_binary2<mod_op, T0, BaseT>::construct(_0, _1);
}

//////////////////////////////////
template <typename BaseT0, typename BaseT1>
inline typename impl::make_binary3<mod_op, BaseT0, BaseT1>::type
operator%(actor<BaseT0> const& _0, actor<BaseT1> const& _1)
{
    return impl::make_binary3<mod_op, BaseT0, BaseT1>::construct(_0, _1);
}

///////////////////////////////////////////////////////////////////////////////
//
//  and lazy operator (infix &)
//
///////////////////////////////////////////////////////////////////////////////
struct and_op {

    template <typename T0, typename T1>
    struct result {

        typedef typename binary_operator<and_op, T0, T1>
            ::result_type type;
    };

    template <typename T0, typename T1>
    typename binary_operator<and_op, T0, T1>::result_type
    operator()(T0& _0, T1& _1) const
    { return binary_operator<and_op, T0, T1>::eval(_0, _1); }
};

//////////////////////////////////
template <typename BaseT, typename T1>
inline typename impl::make_binary1<and_op, BaseT, T1>::type
operator&(actor<BaseT> const& _0, T1 CREF _1)
{
    return impl::make_binary1<and_op, BaseT, T1>::construct(_0, _1);
}

//////////////////////////////////
template <typename T0, typename BaseT>
inline typename impl::make_binary2<and_op, T0, BaseT>::type
operator&(T0 CREF _0, actor<BaseT> const& _1)
{
    return impl::make_binary2<and_op, T0, BaseT>::construct(_0, _1);
}

//////////////////////////////////
template <typename BaseT0, typename BaseT1>
inline typename impl::make_binary3<and_op, BaseT0, BaseT1>::type
operator&(actor<BaseT0> const& _0, actor<BaseT1> const& _1)
{
    return impl::make_binary3<and_op, BaseT0, BaseT1>::construct(_0, _1);
}

///////////////////////////////////////////////////////////////////////////////
//
//  or lazy operator (infix |)
//
///////////////////////////////////////////////////////////////////////////////
struct or_op {

    template <typename T0, typename T1>
    struct result {

        typedef typename binary_operator<or_op, T0, T1>
            ::result_type type;
    };

    template <typename T0, typename T1>
    typename binary_operator<or_op, T0, T1>::result_type
    operator()(T0& _0, T1& _1) const
    { return binary_operator<or_op, T0, T1>::eval(_0, _1); }
};

//////////////////////////////////
template <typename BaseT, typename T1>
inline typename impl::make_binary1<or_op, BaseT, T1>::type
operator|(actor<BaseT> const& _0, T1 CREF _1)
{
    return impl::make_binary1<or_op, BaseT, T1>::construct(_0, _1);
}

//////////////////////////////////
template <typename T0, typename BaseT>
inline typename impl::make_binary2<or_op, T0, BaseT>::type
operator|(T0 CREF _0, actor<BaseT> const& _1)
{
    return impl::make_binary2<or_op, T0, BaseT>::construct(_0, _1);
}

//////////////////////////////////
template <typename BaseT0, typename BaseT1>
inline typename impl::make_binary3<or_op, BaseT0, BaseT1>::type
operator|(actor<BaseT0> const& _0, actor<BaseT1> const& _1)
{
    return impl::make_binary3<or_op, BaseT0, BaseT1>::construct(_0, _1);
}

///////////////////////////////////////////////////////////////////////////////
//
//  xor lazy operator (infix ^)
//
///////////////////////////////////////////////////////////////////////////////
struct xor_op {

    template <typename T0, typename T1>
    struct result {

        typedef typename binary_operator<xor_op, T0, T1>
            ::result_type type;
    };

    template <typename T0, typename T1>
    typename binary_operator<xor_op, T0, T1>::result_type
    operator()(T0& _0, T1& _1) const
    { return binary_operator<xor_op, T0, T1>::eval(_0, _1); }
};

//////////////////////////////////
template <typename BaseT, typename T1>
inline typename impl::make_binary1<xor_op, BaseT, T1>::type
operator^(actor<BaseT> const& _0, T1 CREF _1)
{
    return impl::make_binary1<xor_op, BaseT, T1>::construct(_0, _1);
}

//////////////////////////////////
template <typename T0, typename BaseT>
inline typename impl::make_binary2<xor_op, T0, BaseT>::type
operator^(T0 CREF _0, actor<BaseT> const& _1)
{
    return impl::make_binary2<xor_op, T0, BaseT>::construct(_0, _1);
}

//////////////////////////////////
template <typename BaseT0, typename BaseT1>
inline typename impl::make_binary3<xor_op, BaseT0, BaseT1>::type
operator^(actor<BaseT0> const& _0, actor<BaseT1> const& _1)
{
    return impl::make_binary3<xor_op, BaseT0, BaseT1>::construct(_0, _1);
}

///////////////////////////////////////////////////////////////////////////////
//
//  shift left lazy operator (infix <<)
//
///////////////////////////////////////////////////////////////////////////////
struct shift_l_op {

    template <typename T0, typename T1>
    struct result {

        typedef typename binary_operator<shift_l_op, T0, T1>
            ::result_type type;
    };

    template <typename T0, typename T1>
    typename binary_operator<shift_l_op, T0, T1>::result_type
    operator()(T0& _0, T1& _1) const
    { return binary_operator<shift_l_op, T0, T1>::eval(_0, _1); }
};

//////////////////////////////////
template <typename BaseT, typename T1>
inline typename impl::make_binary1<shift_l_op, BaseT, T1>::type
operator<<(actor<BaseT> const& _0, T1 CREF _1)
{
    return impl::make_binary1<shift_l_op, BaseT, T1>::construct(_0, _1);
}

//////////////////////////////////
template <typename T0, typename BaseT>
inline typename impl::make_binary2<shift_l_op, T0, BaseT>::type
operator<<(T0 CREF _0, actor<BaseT> const& _1)
{
    return impl::make_binary2<shift_l_op, T0, BaseT>::construct(_0, _1);
}

//////////////////////////////////
template <typename BaseT0, typename BaseT1>
inline typename impl::make_binary3<shift_l_op, BaseT0, BaseT1>::type
operator<<(actor<BaseT0> const& _0, actor<BaseT1> const& _1)
{
    return impl::make_binary3<shift_l_op, BaseT0, BaseT1>::construct(_0, _1);
}

///////////////////////////////////////////////////////////////////////////////
//
//  shift right lazy operator (infix >>)
//
///////////////////////////////////////////////////////////////////////////////
struct shift_r_op {

    template <typename T0, typename T1>
    struct result {

        typedef typename binary_operator<shift_r_op, T0, T1>
            ::result_type type;
    };

    template <typename T0, typename T1>
    typename binary_operator<shift_r_op, T0, T1>::result_type
    operator()(T0& _0, T1& _1) const
    { return binary_operator<shift_r_op, T0, T1>::eval(_0, _1); }
};

//////////////////////////////////
template <typename BaseT, typename T1>
inline typename impl::make_binary1<shift_r_op, BaseT, T1>::type
operator>>(actor<BaseT> const& _0, T1 CREF _1)
{
    return impl::make_binary1<shift_r_op, BaseT, T1>::construct(_0, _1);
}

//////////////////////////////////
template <typename T0, typename BaseT>
inline typename impl::make_binary2<shift_r_op, T0, BaseT>::type
operator>>(T0 CREF _0, actor<BaseT> const& _1)
{
    return impl::make_binary2<shift_r_op, T0, BaseT>::construct(_0, _1);
}

//////////////////////////////////
template <typename BaseT0, typename BaseT1>
inline typename impl::make_binary3<shift_r_op, BaseT0, BaseT1>::type
operator>>(actor<BaseT0> const& _0, actor<BaseT1> const& _1)
{
    return impl::make_binary3<shift_r_op, BaseT0, BaseT1>::construct(_0, _1);
}

///////////////////////////////////////////////////////////////////////////////
//
//  equal lazy operator (infix ==)
//
///////////////////////////////////////////////////////////////////////////////
struct eq_op {

    template <typename T0, typename T1>
    struct result {

        typedef typename binary_operator<eq_op, T0, T1>
            ::result_type type;
    };

    template <typename T0, typename T1>
    typename binary_operator<eq_op, T0, T1>::result_type
    operator()(T0& _0, T1& _1) const
    { return binary_operator<eq_op, T0, T1>::eval(_0, _1); }
};

//////////////////////////////////
template <typename BaseT, typename T1>
inline typename impl::make_binary1<eq_op, BaseT, T1>::type
operator==(actor<BaseT> const& _0, T1 CREF _1)
{
    return impl::make_binary1<eq_op, BaseT, T1>::construct(_0, _1);
}

//////////////////////////////////
template <typename T0, typename BaseT>
inline typename impl::make_binary2<eq_op, T0, BaseT>::type
operator==(T0 CREF _0, actor<BaseT> const& _1)
{
    return impl::make_binary2<eq_op, T0, BaseT>::construct(_0, _1);
}

//////////////////////////////////
template <typename BaseT0, typename BaseT1>
inline typename impl::make_binary3<eq_op, BaseT0, BaseT1>::type
operator==(actor<BaseT0> const& _0, actor<BaseT1> const& _1)
{
    return impl::make_binary3<eq_op, BaseT0, BaseT1>::construct(_0, _1);
}

///////////////////////////////////////////////////////////////////////////////
//
//  not equal lazy operator (infix !=)
//
///////////////////////////////////////////////////////////////////////////////
struct not_eq_op {

    template <typename T0, typename T1>
    struct result {

        typedef typename binary_operator<not_eq_op, T0, T1>
            ::result_type type;
    };

    template <typename T0, typename T1>
    typename binary_operator<not_eq_op, T0, T1>::result_type
    operator()(T0& _0, T1& _1) const
    { return binary_operator<not_eq_op, T0, T1>::eval(_0, _1); }
};

//////////////////////////////////
template <typename BaseT, typename T1>
inline typename impl::make_binary1<not_eq_op, BaseT, T1>::type
operator!=(actor<BaseT> const& _0, T1 CREF _1)
{
    return impl::make_binary1<not_eq_op, BaseT, T1>::construct(_0, _1);
}

//////////////////////////////////
template <typename T0, typename BaseT>
inline typename impl::make_binary2<not_eq_op, T0, BaseT>::type
operator!=(T0 CREF _0, actor<BaseT> const& _1)
{
    return impl::make_binary2<not_eq_op, T0, BaseT>::construct(_0, _1);
}

//////////////////////////////////
template <typename BaseT0, typename BaseT1>
inline typename impl::make_binary3<not_eq_op, BaseT0, BaseT1>::type
operator!=(actor<BaseT0> const& _0, actor<BaseT1> const& _1)
{
    return impl::make_binary3<not_eq_op, BaseT0, BaseT1>::construct(_0, _1);
}

///////////////////////////////////////////////////////////////////////////////
//
//  less than lazy operator (infix <)
//
///////////////////////////////////////////////////////////////////////////////
struct lt_op {

    template <typename T0, typename T1>
    struct result {

        typedef typename binary_operator<lt_op, T0, T1>
            ::result_type type;
    };

    template <typename T0, typename T1>
    typename binary_operator<lt_op, T0, T1>::result_type
    operator()(T0& _0, T1& _1) const
    { return binary_operator<lt_op, T0, T1>::eval(_0, _1); }
};

//////////////////////////////////
template <typename BaseT, typename T1>
inline typename impl::make_binary1<lt_op, BaseT, T1>::type
operator<(actor<BaseT> const& _0, T1 CREF _1)
{
    return impl::make_binary1<lt_op, BaseT, T1>::construct(_0, _1);
}

//////////////////////////////////
template <typename T0, typename BaseT>
inline typename impl::make_binary2<lt_op, T0, BaseT>::type
operator<(T0 CREF _0, actor<BaseT> const& _1)
{
    return impl::make_binary2<lt_op, T0, BaseT>::construct(_0, _1);
}

//////////////////////////////////
template <typename BaseT0, typename BaseT1>
inline typename impl::make_binary3<lt_op, BaseT0, BaseT1>::type
operator<(actor<BaseT0> const& _0, actor<BaseT1> const& _1)
{
    return impl::make_binary3<lt_op, BaseT0, BaseT1>::construct(_0, _1);
}

///////////////////////////////////////////////////////////////////////////////
//
//  less than equal lazy operator (infix <=)
//
///////////////////////////////////////////////////////////////////////////////
struct lt_eq_op {

    template <typename T0, typename T1>
    struct result {

        typedef typename binary_operator<lt_eq_op, T0, T1>
            ::result_type type;
    };

    template <typename T0, typename T1>
    typename binary_operator<lt_eq_op, T0, T1>::result_type
    operator()(T0& _0, T1& _1) const
    { return binary_operator<lt_eq_op, T0, T1>::eval(_0, _1); }
};

//////////////////////////////////
template <typename BaseT, typename T1>
inline typename impl::make_binary1<lt_eq_op, BaseT, T1>::type
operator<=(actor<BaseT> const& _0, T1 CREF _1)
{
    return impl::make_binary1<lt_eq_op, BaseT, T1>::construct(_0, _1);
}

//////////////////////////////////
template <typename T0, typename BaseT>
inline typename impl::make_binary2<lt_eq_op, T0, BaseT>::type
operator<=(T0 CREF _0, actor<BaseT> const& _1)
{
    return impl::make_binary2<lt_eq_op, T0, BaseT>::construct(_0, _1);
}

//////////////////////////////////
template <typename BaseT0, typename BaseT1>
inline typename impl::make_binary3<lt_eq_op, BaseT0, BaseT1>::type
operator<=(actor<BaseT0> const& _0, actor<BaseT1> const& _1)
{
    return impl::make_binary3<lt_eq_op, BaseT0, BaseT1>::construct(_0, _1);
}

///////////////////////////////////////////////////////////////////////////////
//
//  greater than lazy operator (infix >)
//
///////////////////////////////////////////////////////////////////////////////
struct gt_op {

    template <typename T0, typename T1>
    struct result {

        typedef typename binary_operator<gt_op, T0, T1>
            ::result_type type;
    };

    template <typename T0, typename T1>
    typename binary_operator<gt_op, T0, T1>::result_type
    operator()(T0& _0, T1& _1) const
    { return binary_operator<gt_op, T0, T1>::eval(_0, _1); }
};

//////////////////////////////////
template <typename BaseT, typename T1>
inline typename impl::make_binary1<gt_op, BaseT, T1>::type
operator>(actor<BaseT> const& _0, T1 CREF _1)
{
    return impl::make_binary1<gt_op, BaseT, T1>::construct(_0, _1);
}

//////////////////////////////////
template <typename T0, typename BaseT>
inline typename impl::make_binary2<gt_op, T0, BaseT>::type
operator>(T0 CREF _0, actor<BaseT> const& _1)
{
    return impl::make_binary2<gt_op, T0, BaseT>::construct(_0, _1);
}

//////////////////////////////////
template <typename BaseT0, typename BaseT1>
inline typename impl::make_binary3<gt_op, BaseT0, BaseT1>::type
operator>(actor<BaseT0> const& _0, actor<BaseT1> const& _1)
{
    return impl::make_binary3<gt_op, BaseT0, BaseT1>::construct(_0, _1);
}

///////////////////////////////////////////////////////////////////////////////
//
//  greater than equal lazy operator (infix >=)
//
///////////////////////////////////////////////////////////////////////////////
struct gt_eq_op {

    template <typename T0, typename T1>
    struct result {

        typedef typename binary_operator<gt_eq_op, T0, T1>
            ::result_type type;
    };

    template <typename T0, typename T1>
    typename binary_operator<gt_eq_op, T0, T1>::result_type
    operator()(T0& _0, T1& _1) const
    { return binary_operator<gt_eq_op, T0, T1>::eval(_0, _1); }
};

//////////////////////////////////
template <typename BaseT, typename T1>
inline typename impl::make_binary1<gt_eq_op, BaseT, T1>::type
operator>=(actor<BaseT> const& _0, T1 CREF _1)
{
    return impl::make_binary1<gt_eq_op, BaseT, T1>::construct(_0, _1);
}

//////////////////////////////////
template <typename T0, typename BaseT>
inline typename impl::make_binary2<gt_eq_op, T0, BaseT>::type
operator>=(T0 CREF _0, actor<BaseT> const& _1)
{
    return impl::make_binary2<gt_eq_op, T0, BaseT>::construct(_0, _1);
}

//////////////////////////////////
template <typename BaseT0, typename BaseT1>
inline typename impl::make_binary3<gt_eq_op, BaseT0, BaseT1>::type
operator>=(actor<BaseT0> const& _0, actor<BaseT1> const& _1)
{
    return impl::make_binary3<gt_eq_op, BaseT0, BaseT1>::construct(_0, _1);
}

///////////////////////////////////////////////////////////////////////////////
//
//  logical and lazy operator (infix &&)
//
//  The logical_and_composite class and its corresponding generators are
//  provided to allow short-circuit evaluation of the operator's
//  operands.
//
///////////////////////////////////////////////////////////////////////////////
template <typename A0, typename A1>
struct logical_and_composite {

    typedef logical_and_composite<A0, A1> self_t;

    template <typename TupleT>
    struct result {

        typedef typename binary_operator<logical_and_op,
            typename actor_result<A0, TupleT>::plain_type,
            typename actor_result<A1, TupleT>::plain_type
        >::result_type type;
    };

    logical_and_composite(A0 const& _0, A1 const& _1)
    :   a0(_0), a1(_1) {}

    template <typename TupleT>
    typename actor_result<self_t, TupleT>::type
    eval(TupleT const& args) const
    {
        return a0.eval(args) && a1.eval(args);
    }

    A0 a0; A1 a1; //  actors
};

#if !(defined(__ICL) && __ICL <= 500)
//////////////////////////////////
template <typename BaseT, typename T1>
inline actor<logical_and_composite
<actor<BaseT>, typename as_actor<T1>::type> >
operator&&(actor<BaseT> const& _0, T1 CREF _1)
{
    return logical_and_composite
        <actor<BaseT>, typename as_actor<T1>::type>
        (_0, as_actor<T1>::convert(_1));
}

//////////////////////////////////
template <typename T0, typename BaseT>
inline actor<logical_and_composite
<typename as_actor<T0>::type, actor<BaseT> > >
operator&&(T0 CREF _0, actor<BaseT> const& _1)
{
    return logical_and_composite
        <typename as_actor<T0>::type, actor<BaseT> >
        (as_actor<T0>::convert(_0), _1);
}

//////////////////////////////////
template <typename BaseT0, typename BaseT1>
inline actor<logical_and_composite
<actor<BaseT0>, actor<BaseT1> > >
operator&&(actor<BaseT0> const& _0, actor<BaseT1> const& _1)
{
    return logical_and_composite
        <actor<BaseT0>, actor<BaseT1> >
        (_0, _1);
}
#else
//////////////////////////////////
template <typename T0, typename T1>
inline actor<logical_and_composite
<typename as_actor<T0>::type, typename as_actor<T1>::type> >
operator&&(T0 CREF _0, T1 CREF _1)
{
    return logical_and_composite
        <typename as_actor<T0>::type, typename as_actor<T1>::type>
        (as_actor<T0>::convert(_0), as_actor<T1>::convert(_1));
}
#endif // !(__ICL && __ICL <= 500)

///////////////////////////////////////////////////////////////////////////////
//
//  logical or lazy operator (infix ||)
//
//  The logical_or_composite class and its corresponding generators are
//  provided to allow short-circuit evaluation of the operator's
//  operands.
//
///////////////////////////////////////////////////////////////////////////////
template <typename A0, typename A1>
struct logical_or_composite {

    typedef logical_or_composite<A0, A1> self_t;

    template <typename TupleT>
    struct result {

        typedef typename binary_operator<logical_or_op,
            typename actor_result<A0, TupleT>::plain_type,
            typename actor_result<A1, TupleT>::plain_type
        >::result_type type;
    };

    logical_or_composite(A0 const& _0, A1 const& _1)
    :   a0(_0), a1(_1) {}

    template <typename TupleT>
    typename actor_result<self_t, TupleT>::type
    eval(TupleT const& args) const
    {
        return a0.eval(args) || a1.eval(args);
    }

    A0 a0; A1 a1; //  actors
};

//////////////////////////////////
template <typename BaseT, typename T1>
inline actor<logical_or_composite
<actor<BaseT>, typename as_actor<T1>::type> >
operator||(actor<BaseT> const& _0, T1 CREF _1)
{
    return logical_or_composite
        <actor<BaseT>, typename as_actor<T1>::type>
        (_0, as_actor<T1>::convert(_1));
}

//////////////////////////////////
template <typename T0, typename BaseT>
inline actor<logical_or_composite
<typename as_actor<T0>::type, actor<BaseT> > >
operator||(T0 CREF _0, actor<BaseT> const& _1)
{
    return logical_or_composite
        <typename as_actor<T0>::type, actor<BaseT> >
        (as_actor<T0>::convert(_0), _1);
}

//////////////////////////////////
template <typename BaseT0, typename BaseT1>
inline actor<logical_or_composite
<actor<BaseT0>, actor<BaseT1> > >
operator||(actor<BaseT0> const& _0, actor<BaseT1> const& _1)
{
    return logical_or_composite
        <actor<BaseT0>, actor<BaseT1> >
        (_0, _1);
}

}   //  namespace phoenix

#undef CREF
#endif
