#ifndef BOOST_PROTO_CONTEXT_CALLABLE_HPP_EAN_06_23_2007
#define BOOST_PROTO_CONTEXT_CALLABLE_HPP_EAN_06_23_2007
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/iteration/iterate.hpp>
#include <boost/preprocessor/facilities/intercept.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/selection/max.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/utility/result_of.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/proto/proto_fwd.hpp>
#include <boost/proto/traits.hpp>
namespace boost { namespace proto
{
namespace detail
{
template<typename Context>
struct callable_context_wrapper
: remove_cv<Context>::type
{
callable_context_wrapper();
typedef private_type_ fun_type(...);
operator fun_type *() const;
BOOST_DELETED_FUNCTION(callable_context_wrapper &operator =(callable_context_wrapper const &))
};
template<typename T>
yes_type check_is_expr_handled(T const &);
no_type check_is_expr_handled(private_type_ const &);
template<typename Expr, typename Context, long Arity = Expr::proto_arity_c>
struct is_expr_handled;
template<typename Expr, typename Context>
struct is_expr_handled<Expr, Context, 0>
{
static callable_context_wrapper<Context> &sctx_;
static Expr &sexpr_;
static typename Expr::proto_tag &stag_;
static const bool value =
sizeof(yes_type) ==
sizeof(
detail::check_is_expr_handled(
(sctx_(stag_, proto::value(sexpr_)), 0)
)
);
typedef mpl::bool_<value> type;
};
}
namespace context
{
template<
typename Expr
, typename Context
, long Arity >
struct callable_eval
{};
template<typename Expr, typename Context>
struct callable_eval<Expr, Context, 0>
{
typedef typename proto::result_of::value<Expr const &>::type value_type;
typedef
typename BOOST_PROTO_RESULT_OF<
Context(typename Expr::proto_tag, value_type)
>::type
result_type;
result_type operator ()(Expr &expr, Context &context) const
{
return context(typename Expr::proto_tag(), proto::value(expr));
}
};
template<
typename Context
, typename DefaultCtx >
struct callable_context
{
template<typename Expr, typename ThisContext = Context>
struct eval
: mpl::if_c<
detail::is_expr_handled<Expr, Context>::value
, callable_eval<Expr, ThisContext>
, typename DefaultCtx::template eval<Expr, Context>
>::type
{};
};
}
#include <boost/proto/context/detail/callable_eval.hpp>
}}
#endif