sample10.cpp
来自「Boost provides free peer-reviewed portab」· C++ 代码 · 共 526 行
CPP
526 行
/*============================================================================= Phoenix V1.2.1 Copyright (c) 2001-2003 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)==============================================================================*/#include <vector>#include <algorithm>#include <iostream>#define PHOENIX_LIMIT 5#include <boost/spirit/include/phoenix1_operators.hpp>#include <boost/spirit/include/phoenix1_primitives.hpp>#include <boost/spirit/include/phoenix1_composite.hpp>#include <boost/spirit/include/phoenix1_special_ops.hpp>#include <boost/spirit/include/phoenix1_statements.hpp>#include <boost/spirit/include/phoenix1_functions.hpp>namespace phoenix {/////////////////////////////////////////////////////////////////////////////////// local_tuple//// This *is a* tuple like the one we see in TupleT in any actor// base class' eval member function. local_tuple should look and// feel the same as a tupled-args, that's why it is derived from// TupleArgsT. It has an added member, locs which is another tuple// where the local variables will be stored. locs is mutable to// allow read-write access to our locals regardless of// local_tuple's constness (The eval member function accepts it as// a const argument)./////////////////////////////////////////////////////////////////////////////////template <typename TupleArgsT, typename TupleLocsT>struct local_tuple : public TupleArgsT { local_tuple(TupleArgsT const& args, TupleLocsT const& locs_) : TupleArgsT(args), locs(locs_) {} mutable TupleLocsT locs;};/////////////////////////////////////////////////////////////////////////////////// local_var_result//// This is a return type computer. Given a constant integer N, a// parent index and a tuple, get the Nth local variable type. The// parent index is an integer specifying which parent scope to// access; 0==current scope, 1==parent scope, 2==parent's parent// scope etc.//// This is a metaprogram with partial specializations. There is a// general case, a special case for local_tuples and a terminating// special case for local_tuples.//// General case: If TupleT is not really a local_tuple, we just return nil_t.//// local_tuples case:// Parent index is 0: We get the Nth local variable.// Otherwise: We subclass from local_tuples<N, Parent-1, TupleArgsT>/////////////////////////////////////////////////////////////////////////////////template <int N, int Parent, typename TupleT>struct local_var_result { typedef nil_t type;};//////////////////////////////////template <int N, int Parent, typename TupleArgsT, typename TupleLocsT>struct local_var_result<N, Parent, local_tuple<TupleArgsT, TupleLocsT> >: public local_var_result<N, Parent-1, TupleArgsT> {};//////////////////////////////////template <int N, typename TupleArgsT, typename TupleLocsT>struct local_var_result<N, 0, local_tuple<TupleArgsT, TupleLocsT> > { typedef typename tuple_element<N, TupleLocsT>::type& type; static type get(local_tuple<TupleArgsT, TupleLocsT> const& tuple) { return tuple.locs[tuple_index<N>()]; }};/////////////////////////////////////////////////////////////////////////////////// local_var//// This class looks so curiously like the argument class. local_var// provides access to the Nth local variable packed in the tuple// duo local_tuple above. Parent specifies the Nth parent scope.// 0==current scope, 1==parent scope, 2==parent's parent scope etc.// The member function parent<N>() may be called to provide access// to outer scopes.//// Note that the member function eval expects a local_tuple// argument. Otherwise there will be acompile-time error. local_var// primitives only work within the context of a context_composite// (see below).//// Provided are some predefined local_var actors for 0..N local// variable access: lvar1..locN./////////////////////////////////////////////////////////////////////////////////template <int N, int Parent = 0>struct local_var { typedef local_var<N, Parent> self_t; template <typename TupleT> struct result { typedef typename local_var_result<N, Parent, TupleT>::type type; }; template <typename TupleT> typename actor_result<self_t, TupleT>::type eval(TupleT const& tuple) const { return local_var_result<N, Parent, TupleT>::get(tuple); } template <int PIndex> actor<local_var<N, Parent+PIndex> > parent() const { return local_var<N, Parent+PIndex>(); }};//////////////////////////////////namespace locals { actor<local_var<0> > const result = local_var<0>(); actor<local_var<1> > const lvar1 = local_var<1>(); actor<local_var<2> > const lvar2 = local_var<2>(); actor<local_var<3> > const lvar3 = local_var<3>(); actor<local_var<4> > const lvar4 = local_var<4>();}///////////////////////////////////////////////////////////////////////////////template <int N, int Parent, typename TupleT>struct local_func_result { typedef nil_t type;};//////////////////////////////////template <int N, int Parent, typename TupleArgsT, typename TupleLocsT>struct local_func_result<N, Parent, local_tuple<TupleArgsT, TupleLocsT> >: public local_func_result<N, Parent-1, TupleArgsT> {};//////////////////////////////////template <int N, typename TupleArgsT, typename TupleLocsT>struct local_func_result<N, 0, local_tuple<TupleArgsT, TupleLocsT> > { typedef typename actor_result< typename tuple_element<N, TupleLocsT>::type, local_tuple<TupleArgsT, TupleLocsT> >::type type; template <typename ArgsT> static type eval(local_tuple<ArgsT, TupleLocsT> const& tuple) { return tuple.locs[tuple_index<N>()].eval(tuple); }};template < int N, int Parent, typename A0 = nil_t, typename A1 = nil_t, typename A2 = nil_t, typename A3 = nil_t, typename A4 = nil_t>struct local_function_actor;//////////////////////////////////template <int N, int Parent>struct local_function_base { template <typename TupleT> struct result { typedef typename local_func_result<N, Parent, TupleT>::type type; };};//////////////////////////////////template <int N, int Parent>struct local_function_actor<N, Parent, nil_t, nil_t, nil_t, nil_t, nil_t>: public local_function_base<N, Parent> { template <typename TupleArgsT, typename TupleLocsT> typename local_func_result< N, Parent, local_tuple<TupleArgsT, TupleLocsT> >::type eval(local_tuple<TupleArgsT, TupleLocsT> const& args) const { typedef local_tuple<TupleArgsT, TupleLocsT> local_tuple_t; typedef tuple<> tuple_t; tuple_t local_args; local_tuple<tuple_t, TupleLocsT> local_context(local_args, args.locs); return local_func_result< N, Parent, local_tuple_t> ::eval(local_context); }};//////////////////////////////////template <int N, int Parent, typename A0>struct local_function_actor<N, Parent, A0, nil_t, nil_t, nil_t, nil_t>: public local_function_base<N, Parent> { local_function_actor( A0 const& _0) : a0(_0) {} template <typename TupleArgsT, typename TupleLocsT> typename local_func_result< N, Parent, local_tuple<TupleArgsT, TupleLocsT> >::type eval(local_tuple<TupleArgsT, TupleLocsT> const& args) const { typedef local_tuple<TupleArgsT, TupleLocsT> local_tuple_t; typename actor_result<A0, local_tuple_t>::type r0 = a0.eval(args); typedef tuple< typename actor_result<A0, local_tuple_t>::type > tuple_t; tuple_t local_args(r0); local_tuple<tuple_t, TupleLocsT> local_context(local_args, args.locs); return local_func_result< N, Parent, local_tuple_t> ::eval(local_context); } A0 a0; // actors};namespace impl { template < int N, int Parent, typename T0 = nil_t, typename T1 = nil_t, typename T2 = nil_t, typename T3 = nil_t, typename T4 = nil_t > struct make_local_function_actor { typedef local_function_actor< N, Parent, typename as_actor<T0>::type, typename as_actor<T1>::type, typename as_actor<T2>::type, typename as_actor<T3>::type, typename as_actor<T4>::type > composite_type; typedef actor<composite_type> type; };}template <int N, int Parent = 0>struct local_function { actor<local_function_actor<N, Parent> > operator()() const { return local_function_actor<N, Parent>(); } template <typename T0> typename impl::make_local_function_actor<N, Parent, T0>::type operator()(T0 const& _0) const { return impl::make_local_function_actor<N, Parent, T0>::composite_type(_0); } template <int PIndex> local_function<N, Parent+PIndex> parent() const { return local_function<N, Parent+PIndex>(); }};//////////////////////////////////namespace locals { local_function<1> const lfun1 = local_function<1>(); local_function<2> const lfun2 = local_function<2>(); local_function<3> const lfun3 = local_function<3>(); local_function<4> const lfun4 = local_function<4>();}/////////////////////////////////////////////////////////////////////////////////// context_composite//// This class encapsulates an actor and some local variable// initializers packed in a tuple.//// context_composite is just like a proxy and delegates the actual// evaluation to the actor. The actor does the actual work. In the// eval member function, before invoking the embedded actor's eval// member function, we first stuff an instance of our locals and// bundle both 'args' and 'locals' in a local_tuple. This// local_tuple instance is created in the stack initializing it// with our locals member. We then pass this local_tuple instance// as an argument to the actor's eval member function./////////////////////////////////////////////////////////////////////////////////template <typename ActorT, typename LocsT>struct context_composite { typedef context_composite<ActorT, LocsT> self_t; template <typename TupleT> struct result { typedef typename tuple_element<0, LocsT>::type type; }; context_composite(ActorT const& actor_, LocsT const& locals_) : actor(actor_), locals(locals_) {} template <typename TupleT> typename tuple_element<0, LocsT>::type eval(TupleT const& args) const { local_tuple<TupleT, LocsT> local_context(args, locals); actor.eval(local_context); return local_context.locs[tuple_index<0>()]; } ActorT actor; LocsT locals;};/////////////////////////////////////////////////////////////////////////////////// context_gen//// At construction time, this class is given some local var-// initializers packed in a tuple. We just store this for later.// The operator[] of this class creates the actual context_composite// given an actor. This is responsible for the construct// context<types>[actor]./////////////////////////////////////////////////////////////////////////////////template <typename LocsT>struct context_gen { context_gen(LocsT const& locals_) : locals(locals_) {} template <typename ActorT> actor<context_composite<typename as_actor<ActorT>::type, LocsT> > operator[](ActorT const& actor) { return context_composite<typename as_actor<ActorT>::type, LocsT> (as_actor<ActorT>::convert(actor), locals); } LocsT locals;};/////////////////////////////////////////////////////////////////////////////////// Front end generator functions. These generators are overloaded for// 1..N local variables. context<T0,... TN>(i0,...iN) generate// context_gen objects (see above)./////////////////////////////////////////////////////////////////////////////////template <typename T0>inline context_gen<tuple<T0> >context(){ typedef tuple<T0> tuple_t; return context_gen<tuple_t>(tuple_t(T0()));}//////////////////////////////////template <typename T0, typename T1>inline context_gen<tuple<T0, T1> >context( T1 const& _1 = T1()){ typedef tuple<T0, T1> tuple_t; return context_gen<tuple_t>(tuple_t(T0(), _1));}//////////////////////////////////template <typename T0, typename T1, typename T2>inline context_gen<tuple<T0, T1, T2> >context( T1 const& _1 = T1(), T2 const& _2 = T2()){ typedef tuple<T0, T1, T2> tuple_t; return context_gen<tuple_t>(tuple_t(T0(), _1, _2));}//////////////////////////////////template <typename T0, typename T1, typename T2, typename T3>inline context_gen<tuple<T0, T1, T2, T3> >context( T1 const& _1 = T1(), T2 const& _2 = T2(), T3 const& _3 = T3()){ typedef tuple<T0, T1, T2, T3> tuple_t; return context_gen<tuple_t>(tuple_t(T0(), _1, _2, _3));}//////////////////////////////////template <typename T0, typename T1, typename T2, typename T3, typename T4>inline context_gen<tuple<T0, T1, T2, T3, T4> >context( T1 const& _1 = T1(), T2 const& _2 = T2(), T3 const& _3 = T3(), T4 const& _4 = T4()){ typedef tuple<T0, T1, T2, T3, T4> tuple_t; return context_gen<tuple_t>(tuple_t(T0(), _1, _2, _3, _4));}///////////////////////////////////////////////////////////////////////////////}//////////////////////////////////using namespace std;using namespace phoenix;using namespace phoenix::locals;//////////////////////////////////intmain(){ int _10 = 10;#ifndef __BORLANDC__ context<nil_t> ( 1000, // lvar1: local int variable cout << arg1 << '\n', // lfun2: local function w/ 1 argument (arg1) lvar1 * 2, // lfun3: local function that accesses local variable lvar1 lfun2(2 * arg1) // lfun4: local function that calls local function lfun2 ) [ lfun2(arg1 + 2000), lfun2(val(5000) * 2), lfun2(lvar1 + lfun3()), lfun4(val(55)), cout << lvar1 << '\n', cout << lfun3() << '\n', cout << val("bye bye\n") ] (_10);#else // Borland does not like local variables w/ local functions // we can have local variables (see sample 7..9) *OR* // local functions (this: sample 10) but not both // Sigh... Borland :-{ context<nil_t> ( 12345, cout << arg1 << '\n' ) [ lfun2(arg1 + 687), lfun2(val(9999) * 2), cout << val("bye bye\n") ] (_10);#endif return 0;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?