1 /*============================================================================== 2 Copyright (c) 2005-2010 Joel de Guzman 3 Copyright (c) 2010 Thomas Heller 4 5 Distributed under the Boost Software License, Version 1.0. (See accompanying 6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 ==============================================================================*/ 8 #ifndef BOOST_PHOENIX_CORE_FUNCTION_EQUAL_HPP 9 #define BOOST_PHOENIX_CORE_FUNCTION_EQUAL_HPP 10 11 #include <boost/phoenix/core/limits.hpp> 12 #include <boost/is_placeholder.hpp> 13 #include <boost/mpl/int.hpp> 14 #include <boost/phoenix/core/terminal.hpp> 15 #include <boost/proto/matches.hpp> 16 17 #ifndef BOOST_PHOENIX_NO_VARIADIC_FUNCTION_EQUAL 18 # include <boost/phoenix/core/detail/index_sequence.hpp> 19 #endif 20 21 namespace boost 22 { 23 template <typename> class weak_ptr; 24 } 25 26 namespace boost { namespace phoenix 27 { 28 template <typename> 29 struct actor; 30 31 namespace detail 32 { 33 struct compare 34 : proto::callable 35 { 36 typedef bool result_type; 37 38 template <typename A0, typename A1> operator ()boost::phoenix::detail::compare39 result_type operator()(A0 const & a0, A1 const & a1) const 40 { 41 return a0 == a1; 42 } 43 44 // hard wiring reference_wrapper and weak_ptr here ... 45 // **TODO** find out why boost bind does this ... 46 template <typename A0, typename A1> 47 result_type operator ()boost::phoenix::detail::compare48 operator()( 49 reference_wrapper<A0> const & a0 50 , reference_wrapper<A1> const & a1 51 ) const 52 { 53 return a0.get_pointer() == a1.get_pointer(); 54 } 55 56 template <typename A0, typename A1> 57 result_type operator ()boost::phoenix::detail::compare58 operator()(weak_ptr<A0> const & a0, weak_ptr<A1> const & a1) const 59 { 60 return !(a0 < a1) && !(a1 < a0); 61 } 62 }; 63 64 struct function_equal_otherwise; 65 66 struct function_equal_ 67 : proto::when< 68 proto::if_< 69 proto::matches<proto::_, proto::_state>() 70 , proto::or_< 71 proto::when< 72 proto::terminal<proto::_> 73 , compare( 74 proto::_value 75 , proto::call< 76 proto::_value(proto::_state) 77 > 78 ) 79 > 80 , proto::otherwise<function_equal_otherwise(proto::_, proto::_state)> 81 > 82 , proto::call<function_equal_otherwise()> 83 > 84 > 85 {}; 86 87 struct function_equal_otherwise 88 : proto::callable 89 { 90 typedef bool result_type; 91 operator ()boost::phoenix::detail::function_equal_otherwise92 result_type operator()() const 93 { 94 return false; 95 } 96 97 #ifdef BOOST_PHOENIX_NO_VARIADIC_FUNCTION_EQUAL 98 template <typename Expr1> operator ()boost::phoenix::detail::function_equal_otherwise99 result_type operator()(Expr1 const& e1, Expr1 const& e2) const 100 { 101 return 102 this->evaluate( 103 e1 104 , e2 105 , mpl::int_<proto::arity_of<Expr1>::value - 1>() 106 ); 107 } 108 109 private: 110 template <typename Expr1> 111 static BOOST_FORCEINLINE result_type evaluateboost::phoenix::detail::function_equal_otherwise112 evaluate(Expr1 const& e1, Expr1 const& e2, mpl::int_<0>) 113 { 114 return 115 function_equal_()( 116 proto::child_c<0>(e1) 117 , proto::child_c<0>(e2) 118 ); 119 } 120 121 template <typename Expr1, int N> 122 static BOOST_FORCEINLINE result_type evaluateboost::phoenix::detail::function_equal_otherwise123 evaluate(Expr1 const& e1, Expr1 const& e2, mpl::int_<N>) 124 { 125 return 126 evaluate( 127 e1 128 , e2 129 , mpl::int_<N - 1>() 130 ) && function_equal_()( 131 proto::child_c<N>(e1) 132 , proto::child_c<N>(e2) 133 ); 134 } 135 #else 136 template <typename Expr1> operator ()boost::phoenix::detail::function_equal_otherwise137 result_type operator()(Expr1 const& e1, Expr1 const& e2) const 138 { 139 return 140 this->evaluate( 141 e1 142 , e2 143 , typename make_index_sequence<proto::arity_of<Expr1>::value>::type() 144 ); 145 } 146 147 private: 148 template <typename Expr1, std::size_t... I> 149 static BOOST_FORCEINLINE result_type evaluateboost::phoenix::detail::function_equal_otherwise150 evaluate(Expr1 const& e1, Expr1 const& e2, index_sequence<I...>) 151 { 152 bool result = true; 153 int dummy[] = { (result && ( 154 result = function_equal_()(proto::child_c<I>(e1), proto::child_c<I>(e2)) 155 ))... }; 156 (void)dummy; 157 return result; 158 } 159 #endif 160 }; 161 } 162 163 template <typename Expr1, typename Expr2> function_equal_impl(actor<Expr1> const & a1,actor<Expr2> const & a2)164 inline bool function_equal_impl(actor<Expr1> const& a1, actor<Expr2> const& a2) 165 { 166 return detail::function_equal_()(a1, a2); 167 } 168 169 template <typename Expr1, typename Expr2> function_equal(actor<Expr1> const & a1,actor<Expr2> const & a2)170 inline bool function_equal(actor<Expr1> const& a1, actor<Expr2> const& a2) 171 { 172 return function_equal_impl(a1, a2); 173 } 174 175 }} 176 177 #endif 178 179