function_equal.hpp 5.4 KB

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