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