diff options
Diffstat (limited to 'boost/phoenix/function/lazy_operator.hpp')
-rw-r--r-- | boost/phoenix/function/lazy_operator.hpp | 670 |
1 files changed, 670 insertions, 0 deletions
diff --git a/boost/phoenix/function/lazy_operator.hpp b/boost/phoenix/function/lazy_operator.hpp new file mode 100644 index 0000000000..c88b768e3d --- /dev/null +++ b/boost/phoenix/function/lazy_operator.hpp @@ -0,0 +1,670 @@ +//////////////////////////////////////////////////////////////////////////// +// 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 <cmath> +#include <cstdlib> +#include <boost/phoenix/core.hpp> +#include <boost/phoenix/function.hpp> +#include <boost/function.hpp> + +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 <typename Sig> + struct result; + + template <typename This, typename A0> + struct result<This(A0)> + : boost::remove_reference<A0> + {}; + + template <typename A0> + A0 operator()(A0 const & a0) const + { + return a0; + } + + }; + + + } + + //BOOST_PHOENIX_ADAPT_CALLABLE(id, impl::id, 1) + typedef boost::phoenix::function<impl::Id> 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<Arg1>::type Arg1Type; + typedef typename boost::remove_reference<Arg2>::type Arg2Type; + typedef std::pair<Arg1Type,Arg2Type> type; + typedef std::pair<Arg1Type,Arg2Type> result_type; + }; + } +#endif + + namespace impl + { + + struct make_pair { + + +#ifdef BOOST_RESULT_OF_USE_TR1 + template <typename Sig> + struct result; + // This fails with -O2 unless refs are removed from A1 and A2. + template <typename This, typename A0, typename A1> + struct result<This(A0, A1)> + { + typedef typename result_of::make_pair<A0,A1>::type type; + }; +#else + template <typename Sig> + struct result; + + template <typename This, typename A0, typename A1> + struct result<This(A0, A1)> + : boost::remove_reference<std::pair<A0, A1> > + {}; + +#endif + + + template <typename A0, typename A1> +#ifdef BOOST_RESULT_OF_USE_TR1 + typename result<make_pair(A0,A1)>::type +#else + std::pair<A0, A1> +#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 <typename Sig> + struct result; + + template <typename This, typename A0, typename A1> + struct result<This(A0, A1)> + : boost::remove_reference<A0> + {}; + + template <typename This, typename A0, typename A1, typename A2> + struct result<This(A0, A1, A2)> + : boost::remove_reference<A0> + {}; + + template <typename A0, typename A1> + A0 operator()(A0 const & a0, A1 const & a1) const + { + //A0 res = a0 + a1; + //return res; + return a0 + a1; + } + + template <typename A0, typename A1, typename A2> + A0 operator()(A0 const & a0, A1 const & a1, A2 const & a2) const + { + return a0 + a1 + a2; + } + }; + + struct Minus + { + template <typename Sig> + struct result; + + template <typename This, typename A0, typename A1> + struct result<This(A0, A1)> + : boost::remove_reference<A0> + {}; + + template <typename A0, typename A1> + A0 operator()(A0 const & a0, A1 const & a1) const + { + return a0 - a1; + } + + }; + + struct multiplies + { + template <typename Sig> + struct result; + + template <typename This, typename A0, typename A1> + struct result<This(A0, A1)> + : boost::remove_reference<A0> + {}; + + template <typename A0, typename A1> + A0 operator()(A0 const & a0, A1 const & a1) const + { + return a0 * a1; + } + + }; + + struct divides + { + template <typename Sig> + struct result; + + template <typename This, typename A0, typename A1> + struct result<This(A0, A1)> + : boost::remove_reference<A0> + {}; + + template <typename A0, typename A1> + A0 operator()(A0 const & a0, A1 const & a1) const + { + return a0 / a1; + } + + }; + + struct modulus + { + template <typename Sig> + struct result; + + template <typename This, typename A0, typename A1> + struct result<This(A0, A1)> + : boost::remove_reference<A0> + {}; + + template <typename A0, typename A1> + A0 operator()(A0 const & a0, A1 const & a1) const + { + return a0 % a1; + } + + }; + + struct negate + { + template <typename Sig> + struct result; + + template <typename This, typename A0> + struct result<This(A0)> + : boost::remove_reference<A0> + {}; + + template <typename A0> + A0 operator()(A0 const & a0) const + { + return -a0; + } + }; + + struct equal + { + template <typename Sig> + struct result; + + template <typename This, typename A0, typename A1> + struct result<This(A0,A1)> + { + typedef bool type; + }; + + template <typename A0, typename A1> + bool operator()(A0 const & a0, A1 const & a1) const + { + return a0 == a1; + } + }; + + struct not_equal + { + template <typename Sig> + struct result; + + template <typename This, typename A0, typename A1> + struct result<This(A0,A1)> + { + typedef bool type; + }; + + template <typename A0, typename A1> + bool operator()(A0 const & a0, A1 const & a1) const + { + return a0 != a1; + } + }; + + struct greater + { + template <typename Sig> + struct result; + + template <typename This, typename A0, typename A1> + struct result<This(A0,A1)> + { + typedef bool type; + }; + + template <typename A0, typename A1> + bool operator()(A0 const & a0, A1 const & a1) const + { + return a0 > a1; + } + }; + + struct less + { + template <typename Sig> + struct result; + + template <typename This, typename A0, typename A1> + struct result<This(A0,A1)> + { + typedef bool type; + }; + + template <typename A0, typename A1> + bool operator()(A0 const & a0, A1 const & a1) const + { + return a0 < a1; + } + }; + + struct greater_equal + { + template <typename Sig> + struct result; + + template <typename This, typename A0, typename A1> + struct result<This(A0,A1)> + { + typedef bool type; + }; + + template <typename A0, typename A1> + bool operator()(A0 const & a0, A1 const & a1) const + { + return a0 >= a1; + } + }; + + struct less_equal + { + template <typename Sig> + struct result; + + template <typename This, typename A0, typename A1> + struct result<This(A0,A1)> + { + typedef bool type; + }; + + template <typename A0, typename A1> + bool operator()(A0 const & a0, A1 const & a1) const + { + return a0 <= a1; + } + }; + + struct logical_and + { + template <typename Sig> + struct result; + + template <typename This, typename A0, typename A1> + struct result<This(A0,A1)> + { + typedef bool type; + }; + + template <typename A0, typename A1> + bool operator()(A0 const & a0, A1 const & a1) const + { + return a0 && a1; + } + }; + + struct logical_or + { + template <typename Sig> + struct result; + + template <typename This, typename A0, typename A1> + struct result<This(A0,A1)> + { + typedef bool type; + }; + + template <typename A0, typename A1> + bool operator()(A0 const & a0, A1 const & a1) const + { + return a0 || a1; + } + }; + + struct logical_not + { + template <typename Sig> + struct result; + + template <typename This, typename A0> + struct result<This(A0)> + { + typedef bool type; + }; + + template <typename A0> + bool operator()(A0 const & a0) const + { + return !a0; + } + }; + + struct min + { + template <typename Sig> + struct result; + + template <typename This, typename A0, typename A1> + struct result<This(A0, A1)> + : boost::remove_reference<A0> + {}; + + template <typename A0, typename A1> + A0 operator()(A0 const & a0, A1 const & a1) const + { + if ( a0 < a1 ) return a0; else return a1; + } + + }; + + struct max + { + template <typename Sig> + struct result; + + template <typename This, typename A0, typename A1> + struct result<This(A0, A1)> + : boost::remove_reference<A0> + {}; + + template <typename A0, typename A1> + A0 operator()(A0 const & a0, A1 const & a1) const + { + if ( a0 < a1 ) return a1; else return a0; + } + + }; + + struct Inc + { + template <typename Sig> + struct result; + + template <typename This, typename A0> + struct result<This(A0)> + : boost::remove_reference<A0> + {}; + + template <typename A0> + A0 operator()(A0 const & a0) const + { + return a0 + 1; + } + + }; + + struct Dec + { + template <typename Sig> + struct result; + + template <typename This, typename A0> + struct result<This(A0)> + : boost::remove_reference<A0> + {}; + + template <typename A0> + A0 operator()(A0 const & a0) const + { + return a0 - 1; + } + + }; + + struct Sin + { + template <typename Sig> + struct result; + + template <typename This, typename A0> + struct result<This(A0)> + : boost::remove_reference<A0> + {}; + + template <typename A0> + A0 operator()(A0 const & a0) const + { + return std::sin(a0); + } + + }; + + // Example of templated struct. + // How do I make it callable? + template <typename Result> + struct what { + + typedef Result result_type; + + Result operator()(Result const & r) const + { + return r; + } + // what is not complete - error. + //static boost::function1<Result,Result> res = what<Result>(); + }; + + template <typename Result> + struct what0 { + + typedef Result result_type; + + Result operator()() const + { + return Result(100); + } + + }; + + template <class Result, class F> + class MonomorphicWrapper0 /* : public c_fun_type<Res> */ + { + 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 <class Res, class F> + full0<impl::XMonomorphicWrapper0<Res,F> > monomorphize0( const F& f ) + { + return make_full0( impl::XMonomorphicWrapper0<Res,F>( f ) ); + }*/ + + + // boost::function0<int> res = MonomorphicWrapper0<int,F>(f); + + + template <class Res, class F> + boost::function<Res()> monomorphize0( const F& f ) + { + boost::function0<Res> ff = MonomorphicWrapper0<Res,F>( f ); + //BOOST_PHOENIX_ADAPT_FUNCTION_NULLARY(Res,fres,ff) + return ff; + } + + // This is C++1y + //template <typename Result> + //static boost::function1<Result,Result> res = what<Result>(); + + + } + ///////////////////////////////////////////////////////// + // 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<int, int > what_int = impl::what<int>(); +typedef boost::function1<int,int> fun1_int_int; +typedef boost::function0<int> fun0_int; +boost::function0<int> what0_int = impl::what0<int>(); +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<fun1_int_int> What_arg; +typedef boost::phoenix::function<fun0_int> 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<impl::Plus> Plus; + typedef boost::phoenix::function<impl::Minus> Minus; + typedef boost::phoenix::function<impl::Inc> Inc; + typedef boost::phoenix::function<impl::Dec> Dec; + typedef boost::phoenix::function<impl::Sin> Sin; + Plus plus; + Minus minus; + Inc inc; + Dec dec; + Sin sin; +} + +} + + + + +#endif |