summaryrefslogtreecommitdiff
path: root/boost/phoenix/function/lazy_operator.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/phoenix/function/lazy_operator.hpp')
-rw-r--r--boost/phoenix/function/lazy_operator.hpp670
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