blob: 64dcdcdc762bc6f67d0a7d7b0b91cd87991e3516 [file] [log] [blame]
/*==============================================================================
Copyright (c) 2005-2010 Joel de Guzman
Copyright (c) 2010 Thomas Heller
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_CORE_FUNCTION_EQUAL_HPP
#define BOOST_PHOENIX_CORE_FUNCTION_EQUAL_HPP
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/phoenix/core/limits.hpp>
#include <boost/is_placeholder.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/phoenix/core/terminal.hpp>
#include <boost/proto/matches.hpp>
namespace boost
{
template <typename> class weak_ptr;
}
namespace boost { namespace phoenix
{
template <typename>
struct actor;
namespace detail
{
struct compare
: proto::callable
{
typedef bool result_type;
template <typename A0, typename A1>
result_type operator()(A0 const & a0, A1 const & a1) const
{
return a0 == a1;
}
// hard wiring reference_wrapper and weak_ptr here ...
// **TODO** find out why boost bind does this ...
template <typename A0, typename A1>
result_type
operator()(
reference_wrapper<A0> const & a0
, reference_wrapper<A1> const & a1
) const
{
return a0.get_pointer() == a1.get_pointer();
}
template <typename A0, typename A1>
result_type
operator()(weak_ptr<A0> const & a0, weak_ptr<A1> const & a1) const
{
return !(a0 < a1) && !(a1 < a0);
}
};
struct function_equal_otherwise;
struct function_equal_
: proto::when<
proto::if_<
proto::matches<proto::_, proto::_state>()
, proto::or_<
proto::when<
proto::terminal<proto::_>
, compare(
proto::_value
, proto::call<
proto::_value(proto::_state)
>
)
>
, proto::otherwise<function_equal_otherwise(proto::_, proto::_state)>
>
, proto::call<function_equal_otherwise()>
>
>
{};
struct function_equal_otherwise
: proto::callable
{
typedef bool result_type;
result_type operator()() const
{
return false;
}
template <typename Expr1>
result_type operator()(Expr1 const& e1, Expr1 const& e2) const
{
return
this->evaluate(
e1
, e2
, typename proto::arity_of<Expr1>::type()
);
}
private:
#if !defined(BOOST_PHOENIX_DONT_USE_PREPROCESSED_FILES)
#include <boost/phoenix/core/preprocessed/function_equal.hpp>
#else
#if defined(__WAVE__) && defined(BOOST_PHOENIX_CREATE_PREPROCESSED_FILES)
#pragma wave option(preserve: 2, line: 0, output: "preprocessed/function_equal_" BOOST_PHOENIX_LIMIT_STR ".hpp")
#endif
#define BOOST_PHOENIX_FUNCTION_EQUAL_R(Z, N, DATA) \
&& function_equal_()( \
proto::child_c< N >(e1) \
, proto::child_c< N >(e2) \
) \
/**/
#define BOOST_PHOENIX_FUNCTION_EQUAL(Z, N, DATA) \
template <typename Expr1> \
result_type \
evaluate( \
Expr1 const& e1 \
, Expr1 const& e2 \
, mpl::long_< N > \
) const \
{ \
return \
function_equal_()( \
proto::child_c<0>(e1) \
, proto::child_c<0>(e2) \
) \
BOOST_PP_REPEAT_FROM_TO( \
1 \
, N \
, BOOST_PHOENIX_FUNCTION_EQUAL_R \
, _ \
); \
} \
/**/
BOOST_PP_REPEAT_FROM_TO(
1
, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY)
, BOOST_PHOENIX_FUNCTION_EQUAL
, _
)
#undef BOOST_PHOENIX_FUNCTION_EQUAL_R
#undef BOOST_PHOENIX_FUNCTION_EQUAL
#if defined(__WAVE__) && defined(BOOST_PHOENIX_CREATE_PREPROCESSED_FILES)
#pragma wave option(output: null)
#endif
#endif
};
}
template <typename Expr1, typename Expr2>
inline bool function_equal_impl(actor<Expr1> const& a1, actor<Expr2> const& a2)
{
return detail::function_equal_()(a1, a2);
}
template <typename Expr1, typename Expr2>
inline bool function_equal(actor<Expr1> const& a1, actor<Expr2> const& a2)
{
return function_equal_impl(a1, a2);
}
}}
#endif