⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 operators.hpp

📁 C++的一个好库。。。现在很流行
💻 HPP
📖 第 1 页 / 共 5 页
字号:
/*=============================================================================
    Phoenix V1.2.1
    Copyright (c) 2001-2002 Joel de Guzman

    Use, modification and distribution is subject to 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)
==============================================================================*/
#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>
#include <boost/mpl/if.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< ::boost::long_long_type>          { static int const value = 110; };
template <> struct rank< ::boost::ulong_long_type> { 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 {
    typedef typename boost::mpl::if_c<
        rank<T0>::value < rank<T1>::value,
        T1, T0>::type type;
};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -