Chris@102: //////////////////////////////////////////////////////////////////////////// Chris@102: // lazy operator.hpp Chris@102: // Chris@102: // Build lazy operations for Phoenix equivalents for FC++ Chris@102: // Chris@102: // These are equivalents of the Boost FC++ functoids in operator.hpp Chris@102: // Chris@102: // Implemented so far: Chris@102: // Chris@102: // make_pair Chris@102: // plus minus multiplies divides modulus Chris@102: // negate equal not_equal greater less Chris@102: // greater_equal less_equal logical_and logical_or Chris@102: // logical_not min max inc dec Chris@102: // Chris@102: // These are not from the FC++ operator.hpp but were made for testing purposes. Chris@102: // Chris@102: // identity (renamed id) Chris@102: // sin Chris@102: // Chris@102: // These are now being modified to use boost::phoenix::function Chris@102: // so that they are available for use as arguments. Chris@102: // Types are being defined in capitals e.g. Id id; Chris@102: //////////////////////////////////////////////////////////////////////////// Chris@102: /*============================================================================= Chris@102: Copyright (c) 2000-2003 Brian McNamara and Yannis Smaragdakis Chris@102: Copyright (c) 2001-2007 Joel de Guzman Chris@102: Copyright (c) 2015 John Fletcher Chris@102: Chris@102: Distributed under the Boost Software License, Version 1.0. (See accompanying Chris@102: file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@102: ==============================================================================*/ Chris@102: Chris@102: Chris@102: #ifndef BOOST_PHOENIX_FUNCTION_LAZY_OPERATOR Chris@102: #define BOOST_PHOENIX_FUNCTION_LAZY_OPERATOR Chris@102: Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: Chris@102: namespace boost { Chris@102: Chris@102: namespace phoenix { Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////// Chris@102: // a_unique_type_for_nil Chris@102: ////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: // This may need to be moved elsewhere to define reuser. Chris@102: struct a_unique_type_for_nil { Chris@102: bool operator==( a_unique_type_for_nil ) const { return true; } Chris@102: bool operator< ( a_unique_type_for_nil ) const { return false; } Chris@102: typedef a_unique_type_for_nil value_type; Chris@102: }; Chris@102: // This maybe put into a namespace. Chris@102: a_unique_type_for_nil NIL; Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////// Chris@102: // lazy_exception - renamed from fcpp_exception. Chris@102: ////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: #ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS Chris@102: struct lazy_exception : public std::exception { Chris@102: const char* s; Chris@102: lazy_exception( const char* ss ) : s(ss) {} Chris@102: const char* what() const throw() { return s; } Chris@102: }; Chris@102: #endif Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: // in ref_count.hpp in BoostFC++ Chris@102: typedef unsigned int RefCountType; Chris@102: Chris@102: namespace impl { Chris@102: Chris@102: struct Id Chris@102: { Chris@102: template Chris@102: struct result; Chris@102: Chris@102: template Chris@102: struct result Chris@102: : boost::remove_reference Chris@102: {}; Chris@102: Chris@102: template Chris@102: A0 operator()(A0 const & a0) const Chris@102: { Chris@102: return a0; Chris@102: } Chris@102: Chris@102: }; Chris@102: Chris@102: Chris@102: } Chris@102: Chris@102: //BOOST_PHOENIX_ADAPT_CALLABLE(id, impl::id, 1) Chris@102: typedef boost::phoenix::function Id; Chris@102: Id id; Chris@102: Chris@102: #ifdef BOOST_RESULT_OF_USE_TR1 Chris@102: // Experiment following examples in Chris@102: // phoenix/stl/container/container.hpp Chris@102: Chris@102: namespace result_of { Chris@102: Chris@102: template < Chris@102: typename Arg1 Chris@102: , typename Arg2 Chris@102: > Chris@102: class make_pair Chris@102: { Chris@102: public: Chris@102: typedef typename boost::remove_reference::type Arg1Type; Chris@102: typedef typename boost::remove_reference::type Arg2Type; Chris@102: typedef std::pair type; Chris@102: typedef std::pair result_type; Chris@102: }; Chris@102: } Chris@102: #endif Chris@102: Chris@102: namespace impl Chris@102: { Chris@102: Chris@102: struct make_pair { Chris@102: Chris@102: Chris@102: #ifdef BOOST_RESULT_OF_USE_TR1 Chris@102: template Chris@102: struct result; Chris@102: // This fails with -O2 unless refs are removed from A1 and A2. Chris@102: template Chris@102: struct result Chris@102: { Chris@102: typedef typename result_of::make_pair::type type; Chris@102: }; Chris@102: #else Chris@102: template Chris@102: struct result; Chris@102: Chris@102: template Chris@102: struct result Chris@102: : boost::remove_reference > Chris@102: {}; Chris@102: Chris@102: #endif Chris@102: Chris@102: Chris@102: template Chris@102: #ifdef BOOST_RESULT_OF_USE_TR1 Chris@102: typename result::type Chris@102: #else Chris@102: std::pair Chris@102: #endif Chris@102: operator()(A0 const & a0, A1 const & a1) const Chris@102: { Chris@102: return std::make_pair(a0,a1); Chris@102: } Chris@102: Chris@102: }; Chris@102: } Chris@102: Chris@102: BOOST_PHOENIX_ADAPT_CALLABLE(make_pair, impl::make_pair, 2) Chris@102: Chris@102: namespace impl Chris@102: { Chris@102: Chris@102: // For now I will leave the return type deduction as it is. Chris@102: // I want to look at bringing in the sort of type deduction for Chris@102: // mixed types which I have in FC++. Chris@102: // Also I could look at the case where one of the arguments is Chris@102: // another functor or a Phoenix placeholder. Chris@102: struct Plus Chris@102: { Chris@102: template Chris@102: struct result; Chris@102: Chris@102: template Chris@102: struct result Chris@102: : boost::remove_reference Chris@102: {}; Chris@102: Chris@102: template Chris@102: struct result Chris@102: : boost::remove_reference Chris@102: {}; Chris@102: Chris@102: template Chris@102: A0 operator()(A0 const & a0, A1 const & a1) const Chris@102: { Chris@102: //A0 res = a0 + a1; Chris@102: //return res; Chris@102: return a0 + a1; Chris@102: } Chris@102: Chris@102: template Chris@102: A0 operator()(A0 const & a0, A1 const & a1, A2 const & a2) const Chris@102: { Chris@102: return a0 + a1 + a2; Chris@102: } Chris@102: }; Chris@102: Chris@102: struct Minus Chris@102: { Chris@102: template Chris@102: struct result; Chris@102: Chris@102: template Chris@102: struct result Chris@102: : boost::remove_reference Chris@102: {}; Chris@102: Chris@102: template Chris@102: A0 operator()(A0 const & a0, A1 const & a1) const Chris@102: { Chris@102: return a0 - a1; Chris@102: } Chris@102: Chris@102: }; Chris@102: Chris@102: struct multiplies Chris@102: { Chris@102: template Chris@102: struct result; Chris@102: Chris@102: template Chris@102: struct result Chris@102: : boost::remove_reference Chris@102: {}; Chris@102: Chris@102: template Chris@102: A0 operator()(A0 const & a0, A1 const & a1) const Chris@102: { Chris@102: return a0 * a1; Chris@102: } Chris@102: Chris@102: }; Chris@102: Chris@102: struct divides Chris@102: { Chris@102: template Chris@102: struct result; Chris@102: Chris@102: template Chris@102: struct result Chris@102: : boost::remove_reference Chris@102: {}; Chris@102: Chris@102: template Chris@102: A0 operator()(A0 const & a0, A1 const & a1) const Chris@102: { Chris@102: return a0 / a1; Chris@102: } Chris@102: Chris@102: }; Chris@102: Chris@102: struct modulus Chris@102: { Chris@102: template Chris@102: struct result; Chris@102: Chris@102: template Chris@102: struct result Chris@102: : boost::remove_reference Chris@102: {}; Chris@102: Chris@102: template Chris@102: A0 operator()(A0 const & a0, A1 const & a1) const Chris@102: { Chris@102: return a0 % a1; Chris@102: } Chris@102: Chris@102: }; Chris@102: Chris@102: struct negate Chris@102: { Chris@102: template Chris@102: struct result; Chris@102: Chris@102: template Chris@102: struct result Chris@102: : boost::remove_reference Chris@102: {}; Chris@102: Chris@102: template Chris@102: A0 operator()(A0 const & a0) const Chris@102: { Chris@102: return -a0; Chris@102: } Chris@102: }; Chris@102: Chris@102: struct equal Chris@102: { Chris@102: template Chris@102: struct result; Chris@102: Chris@102: template Chris@102: struct result Chris@102: { Chris@102: typedef bool type; Chris@102: }; Chris@102: Chris@102: template Chris@102: bool operator()(A0 const & a0, A1 const & a1) const Chris@102: { Chris@102: return a0 == a1; Chris@102: } Chris@102: }; Chris@102: Chris@102: struct not_equal Chris@102: { Chris@102: template Chris@102: struct result; Chris@102: Chris@102: template Chris@102: struct result Chris@102: { Chris@102: typedef bool type; Chris@102: }; Chris@102: Chris@102: template Chris@102: bool operator()(A0 const & a0, A1 const & a1) const Chris@102: { Chris@102: return a0 != a1; Chris@102: } Chris@102: }; Chris@102: Chris@102: struct greater Chris@102: { Chris@102: template Chris@102: struct result; Chris@102: Chris@102: template Chris@102: struct result Chris@102: { Chris@102: typedef bool type; Chris@102: }; Chris@102: Chris@102: template Chris@102: bool operator()(A0 const & a0, A1 const & a1) const Chris@102: { Chris@102: return a0 > a1; Chris@102: } Chris@102: }; Chris@102: Chris@102: struct less Chris@102: { Chris@102: template Chris@102: struct result; Chris@102: Chris@102: template Chris@102: struct result Chris@102: { Chris@102: typedef bool type; Chris@102: }; Chris@102: Chris@102: template Chris@102: bool operator()(A0 const & a0, A1 const & a1) const Chris@102: { Chris@102: return a0 < a1; Chris@102: } Chris@102: }; Chris@102: Chris@102: struct greater_equal Chris@102: { Chris@102: template Chris@102: struct result; Chris@102: Chris@102: template Chris@102: struct result Chris@102: { Chris@102: typedef bool type; Chris@102: }; Chris@102: Chris@102: template Chris@102: bool operator()(A0 const & a0, A1 const & a1) const Chris@102: { Chris@102: return a0 >= a1; Chris@102: } Chris@102: }; Chris@102: Chris@102: struct less_equal Chris@102: { Chris@102: template Chris@102: struct result; Chris@102: Chris@102: template Chris@102: struct result Chris@102: { Chris@102: typedef bool type; Chris@102: }; Chris@102: Chris@102: template Chris@102: bool operator()(A0 const & a0, A1 const & a1) const Chris@102: { Chris@102: return a0 <= a1; Chris@102: } Chris@102: }; Chris@102: Chris@102: struct logical_and Chris@102: { Chris@102: template Chris@102: struct result; Chris@102: Chris@102: template Chris@102: struct result Chris@102: { Chris@102: typedef bool type; Chris@102: }; Chris@102: Chris@102: template Chris@102: bool operator()(A0 const & a0, A1 const & a1) const Chris@102: { Chris@102: return a0 && a1; Chris@102: } Chris@102: }; Chris@102: Chris@102: struct logical_or Chris@102: { Chris@102: template Chris@102: struct result; Chris@102: Chris@102: template Chris@102: struct result Chris@102: { Chris@102: typedef bool type; Chris@102: }; Chris@102: Chris@102: template Chris@102: bool operator()(A0 const & a0, A1 const & a1) const Chris@102: { Chris@102: return a0 || a1; Chris@102: } Chris@102: }; Chris@102: Chris@102: struct logical_not Chris@102: { Chris@102: template Chris@102: struct result; Chris@102: Chris@102: template Chris@102: struct result Chris@102: { Chris@102: typedef bool type; Chris@102: }; Chris@102: Chris@102: template Chris@102: bool operator()(A0 const & a0) const Chris@102: { Chris@102: return !a0; Chris@102: } Chris@102: }; Chris@102: Chris@102: struct min Chris@102: { Chris@102: template Chris@102: struct result; Chris@102: Chris@102: template Chris@102: struct result Chris@102: : boost::remove_reference Chris@102: {}; Chris@102: Chris@102: template Chris@102: A0 operator()(A0 const & a0, A1 const & a1) const Chris@102: { Chris@102: if ( a0 < a1 ) return a0; else return a1; Chris@102: } Chris@102: Chris@102: }; Chris@102: Chris@102: struct max Chris@102: { Chris@102: template Chris@102: struct result; Chris@102: Chris@102: template Chris@102: struct result Chris@102: : boost::remove_reference Chris@102: {}; Chris@102: Chris@102: template Chris@102: A0 operator()(A0 const & a0, A1 const & a1) const Chris@102: { Chris@102: if ( a0 < a1 ) return a1; else return a0; Chris@102: } Chris@102: Chris@102: }; Chris@102: Chris@102: struct Inc Chris@102: { Chris@102: template Chris@102: struct result; Chris@102: Chris@102: template Chris@102: struct result Chris@102: : boost::remove_reference Chris@102: {}; Chris@102: Chris@102: template Chris@102: A0 operator()(A0 const & a0) const Chris@102: { Chris@102: return a0 + 1; Chris@102: } Chris@102: Chris@102: }; Chris@102: Chris@102: struct Dec Chris@102: { Chris@102: template Chris@102: struct result; Chris@102: Chris@102: template Chris@102: struct result Chris@102: : boost::remove_reference Chris@102: {}; Chris@102: Chris@102: template Chris@102: A0 operator()(A0 const & a0) const Chris@102: { Chris@102: return a0 - 1; Chris@102: } Chris@102: Chris@102: }; Chris@102: Chris@102: struct Sin Chris@102: { Chris@102: template Chris@102: struct result; Chris@102: Chris@102: template Chris@102: struct result Chris@102: : boost::remove_reference Chris@102: {}; Chris@102: Chris@102: template Chris@102: A0 operator()(A0 const & a0) const Chris@102: { Chris@102: return std::sin(a0); Chris@102: } Chris@102: Chris@102: }; Chris@102: Chris@102: // Example of templated struct. Chris@102: // How do I make it callable? Chris@102: template Chris@102: struct what { Chris@102: Chris@102: typedef Result result_type; Chris@102: Chris@102: Result operator()(Result const & r) const Chris@102: { Chris@102: return r; Chris@102: } Chris@102: // what is not complete - error. Chris@102: //static boost::function1 res = what(); Chris@102: }; Chris@102: Chris@102: template Chris@102: struct what0 { Chris@102: Chris@102: typedef Result result_type; Chris@102: Chris@102: Result operator()() const Chris@102: { Chris@102: return Result(100); Chris@102: } Chris@102: Chris@102: }; Chris@102: Chris@102: template Chris@102: class MonomorphicWrapper0 /* : public c_fun_type */ Chris@102: { Chris@102: F f; Chris@102: public: Chris@102: typedef Result result_type; Chris@102: MonomorphicWrapper0( const F& g ) : f(g) {} Chris@102: Result operator()() const { Chris@102: return f(); Chris@102: } Chris@102: }; Chris@102: Chris@102: /* I need the equivalent of this Chris@102: template Chris@102: full0 > monomorphize0( const F& f ) Chris@102: { Chris@102: return make_full0( impl::XMonomorphicWrapper0( f ) ); Chris@102: }*/ Chris@102: Chris@102: Chris@102: // boost::function0 res = MonomorphicWrapper0(f); Chris@102: Chris@102: Chris@102: template Chris@102: boost::function monomorphize0( const F& f ) Chris@102: { Chris@102: boost::function0 ff = MonomorphicWrapper0( f ); Chris@102: //BOOST_PHOENIX_ADAPT_FUNCTION_NULLARY(Res,fres,ff) Chris@102: return ff; Chris@102: } Chris@102: Chris@102: // This is C++1y Chris@102: //template Chris@102: //static boost::function1 res = what(); Chris@102: Chris@102: Chris@102: } Chris@102: ///////////////////////////////////////////////////////// Chris@102: // Look at this. How to use Phoenix with a templated Chris@102: // struct. First adapt with boost::function and then Chris@102: // convert that to Phoenix!! Chris@102: // I have not found out how to do it directly. Chris@102: ///////////////////////////////////////////////////////// Chris@102: boost::function1 what_int = impl::what(); Chris@102: typedef boost::function1 fun1_int_int; Chris@102: typedef boost::function0 fun0_int; Chris@102: boost::function0 what0_int = impl::what0(); Chris@102: BOOST_PHOENIX_ADAPT_FUNCTION(int,what,what_int,1) Chris@102: BOOST_PHOENIX_ADAPT_FUNCTION_NULLARY(int,what0,what0_int) Chris@102: // And this shows how to make them into argument callable functions. Chris@102: typedef boost::phoenix::function What_arg; Chris@102: typedef boost::phoenix::function What0_arg; Chris@102: What_arg what_arg(what_int); Chris@102: What0_arg what0_arg(what0_int); Chris@102: Chris@102: //BOOST_PHOENIX_ADAPT_CALLABLE(plus, impl::plus, 2) Chris@102: //BOOST_PHOENIX_ADAPT_CALLABLE(plus, impl::plus, 3) Chris@102: //BOOST_PHOENIX_ADAPT_CALLABLE(minus, impl::minus, 2) Chris@102: BOOST_PHOENIX_ADAPT_CALLABLE(multiplies, impl::multiplies, 2) Chris@102: BOOST_PHOENIX_ADAPT_CALLABLE(divides, impl::divides, 2) Chris@102: BOOST_PHOENIX_ADAPT_CALLABLE(modulus, impl::modulus, 2) Chris@102: BOOST_PHOENIX_ADAPT_CALLABLE(negate, impl::negate, 1) Chris@102: BOOST_PHOENIX_ADAPT_CALLABLE(equal, impl::equal, 2) Chris@102: BOOST_PHOENIX_ADAPT_CALLABLE(not_equal, impl::not_equal, 2) Chris@102: BOOST_PHOENIX_ADAPT_CALLABLE(greater, impl::greater, 2) Chris@102: BOOST_PHOENIX_ADAPT_CALLABLE(less, impl::less, 2) Chris@102: BOOST_PHOENIX_ADAPT_CALLABLE(greater_equal, impl::greater_equal, 2) Chris@102: BOOST_PHOENIX_ADAPT_CALLABLE(less_equal, impl::less_equal, 2) Chris@102: BOOST_PHOENIX_ADAPT_CALLABLE(logical_and, impl::logical_and, 2) Chris@102: BOOST_PHOENIX_ADAPT_CALLABLE(logical_or, impl::logical_or, 2) Chris@102: BOOST_PHOENIX_ADAPT_CALLABLE(logical_not, impl::logical_not, 1) Chris@102: BOOST_PHOENIX_ADAPT_CALLABLE(min, impl::min, 2) Chris@102: BOOST_PHOENIX_ADAPT_CALLABLE(max, impl::max, 2) Chris@102: //BOOST_PHOENIX_ADAPT_CALLABLE(inc, impl::inc, 1) Chris@102: //BOOST_PHOENIX_ADAPT_CALLABLE(dec, impl::dec, 1) Chris@102: //BOOST_PHOENIX_ADAPT_CALLABLE(sin, impl::sin, 1) Chris@102: Chris@102: // To use these as arguments they have to be defined like this. Chris@102: typedef boost::phoenix::function Plus; Chris@102: typedef boost::phoenix::function Minus; Chris@102: typedef boost::phoenix::function Inc; Chris@102: typedef boost::phoenix::function Dec; Chris@102: typedef boost::phoenix::function Sin; Chris@102: Plus plus; Chris@102: Minus minus; Chris@102: Inc inc; Chris@102: Dec dec; Chris@102: Sin sin; Chris@102: } Chris@102: Chris@102: } Chris@102: Chris@102: Chris@102: Chris@102: Chris@102: #endif