📄 binders.hpp
字号:
/*=============================================================================
Phoenix v1.2
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_BINDERS_HPP
#define PHOENIX_BINDERS_HPP
///////////////////////////////////////////////////////////////////////////////
#include <boost/spirit/phoenix/functions.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/mpl/if.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace phoenix {
///////////////////////////////////////////////////////////////////////////////
//
// Binders
//
// There are times when it is desireable to bind a simple functor,
// function, member function or member variable for deferred
// evaluation. This can be done through the binding facilities
// provided below. There are template classes:
//
// 1) function_ptr ( function pointer binder )
// 2) functor ( functor pointer binder )
// 3) member_function_ptr ( member function pointer binder )
// 4) member_var_ptr ( member variable pointer binder )
//
// These template classes are specialized lazy function classes for
// functors, function pointers, member function pointers and member
// variable pointers, respectively. These are subclasses of the
// lazy-function class (see functions.hpp). Each of these has a
// corresponding overloaded bind(x) function. Each bind(x) function
// generates a suitable binder object.
//
// Example, given a function foo:
//
// void foo_(int n) { std::cout << n << std::endl; }
//
// Here's how the function foo is bound:
//
// bind(&foo_)
//
// This bind expression results to a lazy-function (see
// functions.hpp) that is lazily evaluated. This bind expression is
// also equivalent to:
//
// function_ptr<void, int> foo = &foo_;
//
// The template parameter of the function_ptr is the return and
// argument types of actual signature of the function to be bound
// read from left to right:
//
// void foo_(int); ---> function_ptr<void, int>
//
// Either bind(&foo_) and its equivalent foo can now be used in the
// same way a lazy function (see functions.hpp) is used:
//
// bind(&foo_)(arg1)
//
// or
//
// foo(arg1)
//
// The latter, of course, being much easier to understand. This is
// now a full-fledged lazy function that can finally be evaluated
// by another function call invocation. A second function call will
// invoke the actual foo function:
//
// int i = 4;
// foo(arg1)(i);
//
// will print out "4".
//
// Binding functors and member functions can be done similarly.
// Here's how to bind a functor (e.g. std::plus<int>):
//
// bind(std::plus<int>())
//
// or
//
// functor<std::plus<int> > plus;
//
// Again, these are full-fledged lazy functions. In this case,
// unlike the first example, expect 2 arguments (std::plus<int>
// needs two arguments lhs and rhs). Either or both of which can be
// lazily bound:
//
// plus(arg1, arg2) // arg1 + arg2
// plus(100, arg1) // 100 + arg1
// plus(100, 200) // 300
//
// A bound member function takes in a pointer or reference to an
// object as the first argument. For instance, given:
//
// struct xyz { void foo(int) const; };
//
// xyz's foo member function can be bound as:
//
// bind(&xyz::foo)
//
// or
//
// member_function_ptr<void, xyz, int> xyz_foo = &xyz::foo;
//
// The template parameter of the member_function_ptr is the return,
// class and argument types of actual signature of the function to
// be bound read from left to right:
//
// void xyz::foo_(int); ---> member_function_ptr<void, xyz, int>
//
// Take note that a member_function_ptr lazy-function expects the
// first argument to be a pointer or reference to an object. Both
// the object (reference or pointer) and the arguments can be
// lazily bound. Examples:
//
// xyz obj;
// xyz_foo(arg1, arg2) // arg1.foo(arg2)
// xyz_foo(obj, arg1) // obj.foo(arg1)
// xyz_foo(obj, 100) // obj.foo(100)
//
// Be reminded that var(obj) must be used to call non-const member
// functions. For example, if xyz was declared as:
//
// struct xyz { void foo(int); };
//
// the pointer or reference to the object must also be non-const.
// Lazily bound arguments are stored as const value by default (see
// variable class in primitives.hpp).
//
// xyz_foo(var(obj), 100) // obj.foo(100)
//
// Finally, member variables can be bound much like member
// functions. For instance, given:
//
// struct xyz { int v; };
//
// xyz::v can be bound as:
//
// bind(&xyz::v)
// or
//
// member_var_ptr<int, xyz> xyz_v = &xyz::v;
//
// The template parameter of the member_var_ptr is the type of the
// variable followed by the class:
//
// int xyz::v; ---> member_var_ptr<int, xyz>
//
// Just like the member_function_ptr, member_var_ptr also expects
// the first argument to be a pointer or reference to an object.
// Both the object (reference or pointer) and the arguments can be
// lazily bound. Examples:
//
// xyz obj;
// xyz_v(arg1) // arg1.v
// xyz_v(obj) // obj.v
//
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//
// Functor binder
//
///////////////////////////////////////////////////////////////////////////////
template <typename FuncT>
struct functor_action : public FuncT {
#if !defined(__BORLANDC__) && (!defined(__MWERKS__) || (__MWERKS__ > 0x3002))
template <
typename A = nil_t
, typename B = nil_t
, typename C = nil_t
#if PHOENIX_LIMIT > 3
, typename D = nil_t
, typename E = nil_t
, typename F = nil_t
#if PHOENIX_LIMIT > 6
, typename G = nil_t
, typename H = nil_t
, typename I = nil_t
#if PHOENIX_LIMIT > 9
, typename J = nil_t
, typename K = nil_t
, typename L = nil_t
#if PHOENIX_LIMIT > 12
, typename M = nil_t
, typename N = nil_t
, typename O = nil_t
#endif
#endif
#endif
#endif
>
struct result { typedef typename FuncT::result_type type; };
#endif
functor_action(FuncT fptr_ = FuncT())
: FuncT(fptr_) {}
};
#if defined(__BORLANDC__) || (defined(__MWERKS__) && (__MWERKS__ <= 0x3002))
///////////////////////////////////////////////////////////////////////////////
//
// The following specializations are needed because Borland and CodeWarrior
// does not accept default template arguments in nested template classes in
// classes (i.e functor_action::result)
//
///////////////////////////////////////////////////////////////////////////////
template <typename FuncT, typename TupleT>
struct composite0_result<functor_action<FuncT>, TupleT> {
typedef typename FuncT::result_type type;
};
//////////////////////////////////
template <typename FuncT, typename TupleT,
typename A>
struct composite1_result<functor_action<FuncT>, TupleT, A> {
typedef typename FuncT::result_type type;
};
//////////////////////////////////
template <typename FuncT, typename TupleT,
typename A, typename B>
struct composite2_result<functor_action<FuncT>, TupleT, A, B> {
typedef typename FuncT::result_type type;
};
//////////////////////////////////
template <typename FuncT, typename TupleT,
typename A, typename B, typename C>
struct composite3_result<functor_action<FuncT>, TupleT, A, B, C> {
typedef typename FuncT::result_type type;
};
#if PHOENIX_LIMIT > 3
//////////////////////////////////
template <typename FuncT, typename TupleT,
typename A, typename B, typename C, typename D>
struct composite4_result<functor_action<FuncT>, TupleT,
A, B, C, D> {
typedef typename FuncT::result_type type;
};
//////////////////////////////////
template <typename FuncT, typename TupleT,
typename A, typename B, typename C, typename D, typename E>
struct composite5_result<functor_action<FuncT>, TupleT,
A, B, C, D, E> {
typedef typename FuncT::result_type type;
};
//////////////////////////////////
template <typename FuncT, typename TupleT,
typename A, typename B, typename C, typename D, typename E,
typename F>
struct composite6_result<functor_action<FuncT>, TupleT,
A, B, C, D, E, F> {
typedef typename FuncT::result_type type;
};
#if PHOENIX_LIMIT > 6
//////////////////////////////////
template <typename FuncT, typename TupleT,
typename A, typename B, typename C, typename D, typename E,
typename F, typename G>
struct composite7_result<functor_action<FuncT>, TupleT,
A, B, C, D, E, F, G> {
typedef typename FuncT::result_type type;
};
//////////////////////////////////
template <typename FuncT, typename TupleT,
typename A, typename B, typename C, typename D, typename E,
typename F, typename G, typename H>
struct composite8_result<functor_action<FuncT>, TupleT,
A, B, C, D, E, F, G, H> {
typedef typename FuncT::result_type type;
};
//////////////////////////////////
template <typename FuncT, typename TupleT,
typename A, typename B, typename C, typename D, typename E,
typename F, typename G, typename H, typename I>
struct composite9_result<functor_action<FuncT>, TupleT,
A, B, C, D, E, F, G, H, I> {
typedef typename FuncT::result_type type;
};
#if PHOENIX_LIMIT > 9
//////////////////////////////////
template <typename FuncT, typename TupleT,
typename A, typename B, typename C, typename D, typename E,
typename F, typename G, typename H, typename I, typename J>
struct composite10_result<functor_action<FuncT>, TupleT,
A, B, C, D, E, F, G, H, I, J> {
typedef typename FuncT::result_type type;
};
//////////////////////////////////
template <typename FuncT, typename TupleT,
typename A, typename B, typename C, typename D, typename E,
typename F, typename G, typename H, typename I, typename J,
typename K>
struct composite11_result<functor_action<FuncT>, TupleT,
A, B, C, D, E, F, G, H, I, J, K> {
typedef typename FuncT::result_type type;
};
//////////////////////////////////
template <typename FuncT, typename TupleT,
typename A, typename B, typename C, typename D, typename E,
typename F, typename G, typename H, typename I, typename J,
typename K, typename L>
struct composite12_result<functor_action<FuncT>, TupleT,
A, B, C, D, E, F, G, H, I, J, K, L> {
typedef typename FuncT::result_type type;
};
#if PHOENIX_LIMIT > 12
//////////////////////////////////
template <typename FuncT, typename TupleT,
typename A, typename B, typename C, typename D, typename E,
typename F, typename G, typename H, typename I, typename J,
typename K, typename L, typename M>
struct composite13_result<functor_action<FuncT>, TupleT,
A, B, C, D, E, F, G, H, I, J, K, L, M> {
typedef typename FuncT::result_type type;
};
//////////////////////////////////
template <typename FuncT, typename TupleT,
typename A, typename B, typename C, typename D, typename E,
typename F, typename G, typename H, typename I, typename J,
typename K, typename L, typename M, typename N>
struct composite14_result<functor_action<FuncT>, TupleT,
A, B, C, D, E, F, G, H, I, J, K, L, M, N> {
typedef typename FuncT::result_type type;
};
//////////////////////////////////
template <typename FuncT, typename TupleT,
typename A, typename B, typename C, typename D, typename E,
typename F, typename G, typename H, typename I, typename J,
typename K, typename L, typename M, typename N, typename O>
struct composite15_result<functor_action<FuncT>, TupleT,
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O> {
typedef typename FuncT::result_type type;
};
#endif
#endif
#endif
#endif
#endif
//////////////////////////////////
template <typename FuncT>
struct functor : public function<functor_action<FuncT> > {
functor(FuncT func)
: function<functor_action<FuncT> >(functor_action<FuncT>(func)) {};
};
//////////////////////////////////
template <typename FuncT>
inline functor<FuncT>
bind(FuncT func)
{
return functor<FuncT>(func);
}
///////////////////////////////////////////////////////////////////////////////
//
// Member variable pointer binder
//
///////////////////////////////////////////////////////////////////////////////
namespace impl {
//////////////////////////////////
template <typename T>
struct as_ptr {
typedef T* pointer_type;
static T* get(T& ref)
{ return &ref; }
};
//////////////////////////////////
template <typename T>
struct as_ptr<T*> {
typedef T* pointer_type;
static T* get(T* ptr)
{ return ptr; }
};
}
//////////////////////////////////
template <typename ActionT, typename ClassT>
struct member_var_ptr_action_result {
typedef typename ActionT::template result<ClassT>::type type;
};
//////////////////////////////////
template <typename T, typename ClassT>
struct member_var_ptr_action {
typedef member_var_ptr_action<T, ClassT> self_t;
template <typename CT>
struct result {
typedef typename boost::mpl::if_<boost::is_const<CT>, T const&, T&
>::type type;
};
typedef T ClassT::*mem_var_ptr_t;
member_var_ptr_action(mem_var_ptr_t ptr_)
: ptr(ptr_) {}
template <typename CT>
typename member_var_ptr_action_result<self_t, CT>::type
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -