#ifndef BOOST_PP_IS_ITERATING ////////////////////////////////////////////////////////////////////////////// // Copyright 20011 Eric Niebler. 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 CURRYABLE_HPP #define CURRYABLE_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef CURRY_MAX_FN_ARITY #define CURRY_MAX_FN_ARITY 10 #endif template struct is_callable_with; template struct curryable; template struct sizer { typedef char (&type)[Size]; }; struct invalid_type { friend invalid_type operator,(invalid_type, int); }; template sizer<2>::type is_invalid(T const &); sizer<1>::type is_invalid(invalid_type const &); struct any { template any(T const &); }; template struct callable_wrap : Fun { #define M0(Z, N, D) \ typedef invalid_type (*BOOST_PP_CAT(function_type, N))( \ BOOST_PP_ENUM_PARAMS_Z(Z, N, any BOOST_PP_INTERCEPT)); \ operator BOOST_PP_CAT(function_type, N)() const volatile; \ /**/ BOOST_PP_REPEAT(CURRY_MAX_FN_ARITY, M0, ~) #undef M0 }; #define M0(Z, N, D) static BOOST_PP_CAT(Arg, N) & BOOST_PP_CAT(arg, N); #define BOOST_PP_LOCAL_MACRO(N) \ template \ struct is_callable_with \ { \ static callable_wrap &fun; \ BOOST_PP_REPEAT(N, M0, ~) \ static bool const value = \ bool(sizeof(is_invalid((fun(BOOST_PP_ENUM_PARAMS(N, arg)), 0)))-1); \ typedef boost::mpl::bool_ type; \ }; \ /**/ #define BOOST_PP_LOCAL_LIMITS (0, BOOST_PP_DEC(CURRY_MAX_FN_ARITY)) #include BOOST_PP_LOCAL_ITERATE() #undef M0 template struct is_natively_callable_with : is_callable_with {}; template struct is_natively_callable_with BOOST_PP_ENUM_TRAILING_PARAMS(CURRY_MAX_FN_ARITY, Arg), void> : is_natively_callable_with {}; #define BOOST_PP_LOCAL_MACRO(N) \ template \ struct is_natively_callable_with BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_SUB(CURRY_MAX_FN_ARITY, N), B), typename boost::disable_if >::type> \ : is_natively_callable_with \ {};\ /**/ #define BOOST_PP_LOCAL_LIMITS (1, BOOST_PP_DEC(CURRY_MAX_FN_ARITY)) #include BOOST_PP_LOCAL_ITERATE() #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, BOOST_PP_DEC(CURRY_MAX_FN_ARITY), "curryable.hpp", 1)) #include BOOST_PP_ITERATE() #endif #else #if BOOST_PP_ITERATION_FLAGS() == 1 #define N BOOST_PP_ITERATION() template struct curryable { Fun fun; #define M0(Z, N, D) BOOST_PP_CAT(Arg, N) BOOST_PP_CAT(arg, N); BOOST_PP_REPEAT(N, M0, ~) #undef M0 #if N == 0 explicit curryable(Fun f = Fun()) : fun(f) {} #else #define M0(Z, N, D) BOOST_PP_CAT(arg, N)(BOOST_PP_CAT(a, N)) curryable(Fun f BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, Arg, a)) : fun(f) BOOST_PP_ENUM_TRAILING(N, M0, ~) {} #undef M0 #endif template struct result; template struct result { typedef curryable type; }; curryable operator()() const { return *this; } #if BOOST_PP_LESS_EQUAL(1, BOOST_PP_DEC(BOOST_PP_SUB(CURRY_MAX_FN_ARITY, N))) #define BOOST_PP_ITERATION_PARAMS_2 (4, (1, BOOST_PP_DEC(BOOST_PP_SUB(CURRY_MAX_FN_ARITY, N)), "curryable.hpp", 2)) #include BOOST_PP_ITERATE() #endif template struct result : boost::result_of {}; template typename boost::result_of::type operator()(BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_SUB(CURRY_MAX_FN_ARITY, N), B, const & b)) const { return fun(BOOST_PP_ENUM_PARAMS(N, arg) BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_PARAMS(BOOST_PP_SUB(CURRY_MAX_FN_ARITY, N), b)); } }; #undef N #else #define X BOOST_PP_ITERATION_1 #define Y BOOST_PP_ITERATION_2 template struct result : boost::mpl::eval_if< is_natively_callable_with , boost::result_of , boost::mpl::identity > > {}; template typename boost::lazy_enable_if, boost::result_of >::type operator()(BOOST_PP_ENUM_BINARY_PARAMS(Y, B, const & b)) const { return fun(BOOST_PP_ENUM_PARAMS(X, arg) BOOST_PP_COMMA_IF(X) BOOST_PP_ENUM_PARAMS(Y, b)); } template typename boost::disable_if, curryable >::type operator()(BOOST_PP_ENUM_BINARY_PARAMS(Y, B, const & b)) const { return curryable(*this BOOST_PP_ENUM_TRAILING_PARAMS(Y, b)); } #undef X #undef Y #endif #endif