diff --git a/sprout/functional/bind/bind.hpp b/sprout/functional/bind/bind.hpp index 805a3b92..2570ab84 100644 --- a/sprout/functional/bind/bind.hpp +++ b/sprout/functional/bind/bind.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -74,6 +75,17 @@ namespace sprout { return const_cast::type>::type&>(arg).get(); } }; + template + class mu, false, false> { + public: + typedef T& result_type; + public: + template + SPROUT_CONSTEXPR result_type operator()(CVRef& arg, Tuple&) const volatile { + //return arg.get(); // ??? + return const_cast::type>::type&>(arg).get(); + } + }; template class mu { private: @@ -113,7 +125,7 @@ namespace sprout { public: template typename result::type - SPROUT_CONSTEXPR operator()(Arg const volatile&, Tuple& tuple) const volatile { + SPROUT_CONSTEXPR operator()(Arg /*const volatile&*/, Tuple& tuple) const volatile { return sprout::forward::type>( sprout::tuples::get<(sprout::is_placeholder::value - 1)>(tuple) ); @@ -164,7 +176,7 @@ namespace sprout { }; template - inline auto volget(sprout::tuples::tuple volatile& tuple) + inline SPROUT_CONSTEXPR auto volget(sprout::tuples::tuple volatile& tuple) -> typename sprout::tuples::tuple_element >::type volatile& { return sprout::tuples::get(const_cast&>(tuple)); @@ -175,6 +187,151 @@ namespace sprout { { return sprout::tuples::get(const_cast const&>(tuple)); } + + template + struct is_variadic_bounds + : public std::false_type + {}; + template + struct is_variadic_bounds< + Bounds, + typename std::enable_if::value>::type + > + : public std::integral_constant< + bool, + (sprout::is_placeholder::value - 1, Bounds>::type>::value + <= -256 + ) + > + {}; + + template + struct tail_bounds_place + : public std::integral_constant + {}; + template + struct tail_bounds_place< + Bounds, + typename std::enable_if::value>::type + > + : public std::integral_constant< + int, + (-256 + - sprout::is_placeholder::value - 1, Bounds>::type>::value + ) + > + {}; + + template + struct bounds_size + : public std::integral_constant< + std::size_t, + sprout::detail::is_variadic_bounds::value + ? (sprout::tuples::tuple_size::value - 1) + (sizeof...(Args) - sprout::detail::tail_bounds_place::value) + : sprout::tuples::tuple_size::value + > + {}; + + template + struct bound_indexes + : public sprout::make_index_tuple::value> + {}; + + template + struct is_variadic_part + : public std::integral_constant< + bool, + sprout::detail::is_variadic_bounds::value && (I >= sprout::tuples::tuple_size::value) + > + {}; + + template + struct bound_element + : public sprout::tuples::tuple_element + {}; + template + struct bound_element< + I, Bounds, + typename std::enable_if::value>::type + > { + public: + typedef sprout::placeholder::value + sprout::detail::tail_bounds_place::value + 1> type; + }; + + template + struct complete_bounds_impl; + template + struct complete_bounds_impl > { + public: + typedef sprout::tuples::tuple...> type; + }; + template + struct complete_bounds + : public sprout::detail::complete_bounds_impl::type> + {}; + + struct get_bound_helper { + public: + template< + sprout::index_t I, typename Bounds, + typename sprout::enabler_if::value && !std::is_volatile::value>::type = sprout::enabler + > + static SPROUT_CONSTEXPR auto + get_bound(Bounds& bound_args) + -> decltype(sprout::tuples::get(bound_args)) + { + return sprout::tuples::get(bound_args); + } + template< + sprout::index_t I, typename Bounds, + typename sprout::enabler_if::value && !std::is_volatile::value>::type = sprout::enabler + > + static SPROUT_CONSTEXPR auto + get_bound(Bounds const& bound_args) + -> decltype(sprout::tuples::get(bound_args)) + { + return sprout::tuples::get(bound_args); + } + template< + sprout::index_t I, typename Bounds, + typename sprout::enabler_if::value && std::is_volatile::value>::type = sprout::enabler + > + static SPROUT_CONSTEXPR auto + get_bound(Bounds volatile& bound_args) + -> decltype(sprout::detail::volget(bound_args)) + { + return sprout::detail::volget(bound_args); + } + template< + sprout::index_t I, typename Bounds, + typename sprout::enabler_if::value && std::is_volatile::value>::type = sprout::enabler + > + static SPROUT_CONSTEXPR auto + get_bound(Bounds const volatile& bound_args) + -> decltype(sprout::detail::volget(bound_args)) + { + return sprout::detail::volget(bound_args); + } + }; + template< + sprout::index_t I, typename Bounds, + typename sprout::enabler_if::type>::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR typename sprout::detail::bound_element::type>::type + get_bound(Bounds&&) { + typedef typename sprout::detail::bound_element::type>::type type; + return type(); + } + template< + sprout::index_t I, typename Bounds, + typename sprout::enabler_if::type>::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR auto + get_bound(Bounds&& bound_args) + -> decltype(sprout::detail::get_bound_helper::get_bound(std::forward(bound_args))) + { + return sprout::detail::get_bound_helper::get_bound(std::forward(bound_args)); + } } // namespace detail // @@ -188,28 +345,81 @@ namespace sprout { { private: typedef binder self_type; - typedef typename sprout::index_pack::type bound_indexes; + typedef sprout::tuples::tuple bounds_type; private: Functor f_; - sprout::tuples::tuple bound_args_; + bounds_type bound_args_; private: template Result call(sprout::tuples::tuple&& args, sprout::index_tuple) { - return f_(sprout::detail::mu()(sprout::tuples::get(bound_args_), args)...); + return f_( + sprout::detail::mu::type>() + (sprout::detail::get_bound(bound_args_), args)... + ); } template SPROUT_CONSTEXPR Result call_c(sprout::tuples::tuple&& args, sprout::index_tuple) const { - return f_(sprout::detail::mu()(sprout::tuples::get(bound_args_), args)...); + return f_( + sprout::detail::mu::type const>() + (sprout::detail::get_bound(bound_args_), args)... + ); } template Result call_v(sprout::tuples::tuple&& args, sprout::index_tuple) volatile { - return f_(sprout::detail::mu()(sprout::detail::volget(bound_args_), args)...); + return f_( + sprout::detail::mu::type volatile>() + (sprout::detail::get_bound(bound_args_), args)... + ); } template SPROUT_CONSTEXPR Result call_cv(sprout::tuples::tuple&& args, sprout::index_tuple) const volatile { - return f_(sprout::detail::mu()(sprout::detail::volget(bound_args_), args)...); + return f_( + sprout::detail::mu::type const volatile>() + (sprout::detail::get_bound(bound_args_), args)... + ); } - public: + private: + template< + typename... Args, sprout::index_t... Indexes + > + static SPROUT_CONSTEXPR decltype( + std::declval()( + sprout::detail::mu::type>() + (sprout::detail::get_bound(std::declval()), std::declval&>())... + ) + ) + call_(sprout::tuples::tuple&& args, sprout::index_tuple); + template< + typename... Args, sprout::index_t... Indexes + > + static SPROUT_CONSTEXPR decltype( + std::declval= 0), typename std::add_const::type>::type&>()( + sprout::detail::mu::type const>() + (sprout::detail::get_bound(std::declval()), std::declval&>())... + ) + ) + call_c_(sprout::tuples::tuple&& args, sprout::index_tuple); + template< + typename... Args, sprout::index_t... Indexes + > + static SPROUT_CONSTEXPR decltype( + std::declval= 0), typename std::add_volatile::type>::type&>()( + sprout::detail::mu::type volatile>() + (sprout::detail::get_bound(std::declval()), std::declval&>())... + ) + ) + call_v_(sprout::tuples::tuple&& args, sprout::index_tuple); + template< + typename... Args, sprout::index_t... Indexes + > + static SPROUT_CONSTEXPR decltype( + std::declval= 0), typename std::add_cv::type>::type&>()( + sprout::detail::mu::type const volatile>() + (sprout::detail::get_bound(std::declval()), std::declval&>())... + ) + ) + call_cv_(sprout::tuples::tuple&& args, sprout::index_tuple); + public: template explicit SPROUT_CONSTEXPR binder(Functor const& f, Args&&... args) : f_(f) @@ -219,70 +429,49 @@ namespace sprout { template< typename... Args, typename Result = decltype( - std::declval()( - sprout::detail::mu()( - std::declval(), - std::declval&>() - )... - ) + call_(std::declval >(), sprout::detail::bound_indexes::make()) ) > Result operator()(Args&&... args) { return call( sprout::tuples::forward_as_tuple(sprout::forward(args)...), - bound_indexes() + sprout::detail::bound_indexes::make() ); } template< typename... Args, typename Result = decltype( - std::declval= 0), typename std::add_const::type>::type>()( - sprout::detail::mu()( - std::declval(), - std::declval&>() - )... - ) + call_c_(std::declval >(), sprout::detail::bound_indexes::make()) ) > SPROUT_CONSTEXPR Result operator()(Args&&... args) const { return call_c( sprout::tuples::forward_as_tuple(sprout::forward(args)...), - bound_indexes() + sprout::detail::bound_indexes::make() ); } template< typename... Args, typename Result = decltype( - std::declval= 0), typename std::add_volatile::type>::type>()( - sprout::detail::mu()( - std::declval(), - std::declval&>() - )... - ) + call_v_(std::declval >(), sprout::detail::bound_indexes::make()) ) > Result operator()(Args&&... args) volatile { return call_v( sprout::tuples::forward_as_tuple(sprout::forward(args)...), - bound_indexes() + sprout::detail::bound_indexes::make() ); } - template< typename... Args, typename Result = decltype( - std::declval= 0), typename std::add_cv::type>::type>()( - sprout::detail::mu()( - std::declval(), - std::declval&>() - )... - ) + call_cv_(std::declval >(), sprout::detail::bound_indexes::make()) ) > SPROUT_CONSTEXPR Result operator()(Args&&... args) const volatile { return call_cv( sprout::tuples::forward_as_tuple(sprout::forward(args)...), - bound_indexes() + sprout::detail::bound_indexes::make() ); } }; @@ -296,7 +485,7 @@ namespace sprout { class res_binder { private: typedef res_binder self_type; - typedef typename sprout::index_pack::type bound_indexes; + typedef sprout::tuples::tuple bounds_type; private: template struct enable_if_void @@ -317,7 +506,7 @@ namespace sprout { typename disable_if_void::type = 0 ) { - return f_(sprout::detail::mu()(sprout::tuples::get(bound_args_), args)...); + return f_(sprout::detail::mu()(sprout::detail::get_bound(bound_args_), args)...); } template Result call( @@ -326,7 +515,7 @@ namespace sprout { typename enable_if_void::type = 0 ) { - f_(sprout::detail::mu()(sprout::tuples::get(bound_args_), args)...); + f_(sprout::detail::mu()(sprout::detail::get_bound(bound_args_), args)...); } template SPROUT_CONSTEXPR Result call( @@ -335,7 +524,7 @@ namespace sprout { typename disable_if_void::type = 0 ) const { - return f_(sprout::detail::mu()(sprout::tuples::get(bound_args_), args)...); + return f_(sprout::detail::mu()(sprout::detail::get_bound(bound_args_), args)...); } template Result call( @@ -344,7 +533,7 @@ namespace sprout { typename enable_if_void::type = 0 ) const { - f_(sprout::detail::mu()(sprout::tuples::get(bound_args_), args)...); + f_(sprout::detail::mu()(sprout::detail::get_bound(bound_args_), args)...); } template Result call( @@ -353,7 +542,7 @@ namespace sprout { typename disable_if_void::type = 0 ) volatile { - return f_(sprout::detail::mu()(sprout::detail::volget(bound_args_), args)...); + return f_(sprout::detail::mu()(sprout::detail::get_bound(bound_args_), args)...); } template Result call( @@ -362,7 +551,7 @@ namespace sprout { typename enable_if_void::type = 0 ) volatile { - f_(sprout::detail::mu()(sprout::detail::volget(bound_args_), args)...); + f_(sprout::detail::mu()(sprout::detail::get_bound(bound_args_), args)...); } template SPROUT_CONSTEXPR Result call( @@ -371,7 +560,7 @@ namespace sprout { typename disable_if_void::type = 0 ) const volatile { - return f_(sprout::detail::mu()(sprout::detail::volget(bound_args_), args)...); + return f_(sprout::detail::mu()(sprout::detail::get_bound(bound_args_), args)...); } template Result call( @@ -380,7 +569,7 @@ namespace sprout { typename enable_if_void::type = 0 ) const volatile { - f_(sprout::detail::mu()(sprout::detail::volget(bound_args_), args)...); + f_(sprout::detail::mu()(sprout::detail::get_bound(bound_args_), args)...); } public: typedef Result result_type; @@ -394,28 +583,28 @@ namespace sprout { result_type operator()(Args&&... args) { return call( sprout::tuples::forward_as_tuple(sprout::forward(args)...), - bound_indexes() + sprout::detail::bound_indexes::make() ); } template SPROUT_CONSTEXPR result_type operator()(Args&&... args) const { return call( sprout::tuples::forward_as_tuple(sprout::forward(args)...), - bound_indexes() + sprout::detail::bound_indexes::make() ); } template result_type operator()(Args&&... args) volatile { return call( sprout::tuples::forward_as_tuple(sprout::forward(args)...), - bound_indexes() + sprout::detail::bound_indexes::make() ); } template SPROUT_CONSTEXPR result_type operator()(Args&&... args) const volatile { return call( sprout::tuples::forward_as_tuple(sprout::forward(args)...), - bound_indexes() + sprout::detail::bound_indexes::make() ); } }; @@ -434,7 +623,12 @@ namespace sprout { namespace detail { template - struct complete_placeholder { + struct complete_placeholder; + template + struct complete_placeholder< + Index, BoundArg, + typename std::enable_if::value == -1)>::type + > { public: typedef BoundArg type; }; @@ -477,7 +671,6 @@ namespace sprout { typedef sprout::detail::maybe_wrap_member_pointer::type> maybe_type; typedef typename maybe_type::type func_type; typedef typename sprout::detail::binder_complete_placeholders::type...>::type type; -// typedef sprout::binder::type...)> type; }; template struct res_bind_helper { @@ -485,7 +678,6 @@ namespace sprout { typedef sprout::detail::maybe_wrap_member_pointer::type> maybe_type; typedef typename maybe_type::type functor_type; typedef typename sprout::detail::res_binder_complete_placeholders::type...>::type type; -// typedef sprout::res_binder::type...)> type; }; } // namespace detail diff --git a/sprout/functional/bind/placeholder.hpp b/sprout/functional/bind/placeholder.hpp index d1b7c4ae..a5a5be77 100644 --- a/sprout/functional/bind/placeholder.hpp +++ b/sprout/functional/bind/placeholder.hpp @@ -9,9 +9,13 @@ namespace sprout { // placeholder // template - struct placeholder {}; + struct placeholder +// : public std::integral_constant + {}; template<> - struct placeholder<-1> { + struct placeholder<-1> +// : public std::integral_constant + { public: template SPROUT_CONSTEXPR operator sprout::placeholder() const { @@ -53,6 +57,38 @@ namespace sprout { SPROUT_STATIC_CONSTEXPR sprout::placeholder<30> _30 = {}; SPROUT_STATIC_CONSTEXPR sprout::placeholder<-1> _ = {}; + + SPROUT_STATIC_CONSTEXPR sprout::placeholder<-256> _va = {}; + SPROUT_STATIC_CONSTEXPR sprout::placeholder<-256 - 1> _1tail = {}; + SPROUT_STATIC_CONSTEXPR sprout::placeholder<-256 - 2> _2tail = {}; + SPROUT_STATIC_CONSTEXPR sprout::placeholder<-256 - 3> _3tail = {}; + SPROUT_STATIC_CONSTEXPR sprout::placeholder<-256 - 4> _4tail = {}; + SPROUT_STATIC_CONSTEXPR sprout::placeholder<-256 - 5> _5tail = {}; + SPROUT_STATIC_CONSTEXPR sprout::placeholder<-256 - 6> _6tail = {}; + SPROUT_STATIC_CONSTEXPR sprout::placeholder<-256 - 7> _7tail = {}; + SPROUT_STATIC_CONSTEXPR sprout::placeholder<-256 - 8> _8tail = {}; + SPROUT_STATIC_CONSTEXPR sprout::placeholder<-256 - 9> _9tail = {}; + SPROUT_STATIC_CONSTEXPR sprout::placeholder<-256 - 10> _10tail = {}; + SPROUT_STATIC_CONSTEXPR sprout::placeholder<-256 - 11> _11tail = {}; + SPROUT_STATIC_CONSTEXPR sprout::placeholder<-256 - 12> _12tail = {}; + SPROUT_STATIC_CONSTEXPR sprout::placeholder<-256 - 13> _13tail = {}; + SPROUT_STATIC_CONSTEXPR sprout::placeholder<-256 - 14> _14tail = {}; + SPROUT_STATIC_CONSTEXPR sprout::placeholder<-256 - 15> _15tail = {}; + SPROUT_STATIC_CONSTEXPR sprout::placeholder<-256 - 16> _16tail = {}; + SPROUT_STATIC_CONSTEXPR sprout::placeholder<-256 - 17> _17tail = {}; + SPROUT_STATIC_CONSTEXPR sprout::placeholder<-256 - 18> _18tail = {}; + SPROUT_STATIC_CONSTEXPR sprout::placeholder<-256 - 19> _19tail = {}; + SPROUT_STATIC_CONSTEXPR sprout::placeholder<-256 - 20> _20tail = {}; + SPROUT_STATIC_CONSTEXPR sprout::placeholder<-256 - 21> _21tail = {}; + SPROUT_STATIC_CONSTEXPR sprout::placeholder<-256 - 22> _22tail = {}; + SPROUT_STATIC_CONSTEXPR sprout::placeholder<-256 - 23> _23tail = {}; + SPROUT_STATIC_CONSTEXPR sprout::placeholder<-256 - 24> _24tail = {}; + SPROUT_STATIC_CONSTEXPR sprout::placeholder<-256 - 25> _25tail = {}; + SPROUT_STATIC_CONSTEXPR sprout::placeholder<-256 - 26> _26tail = {}; + SPROUT_STATIC_CONSTEXPR sprout::placeholder<-256 - 27> _27tail = {}; + SPROUT_STATIC_CONSTEXPR sprout::placeholder<-256 - 28> _28tail = {}; + SPROUT_STATIC_CONSTEXPR sprout::placeholder<-256 - 29> _29tail = {}; + SPROUT_STATIC_CONSTEXPR sprout::placeholder<-256 - 30> _30tail = {}; } // anonymous-namespace } // namespace placeholders using sprout::placeholders::_1; @@ -76,7 +112,7 @@ namespace sprout { using sprout::placeholders::_19; using sprout::placeholders::_20; using sprout::placeholders::_21; - using sprout::placeholders::_2; + using sprout::placeholders::_22; using sprout::placeholders::_23; using sprout::placeholders::_24; using sprout::placeholders::_25; @@ -88,6 +124,38 @@ namespace sprout { using sprout::placeholders::_; + using sprout::placeholders::_va; + using sprout::placeholders::_1tail; + using sprout::placeholders::_2tail; + using sprout::placeholders::_3tail; + using sprout::placeholders::_4tail; + using sprout::placeholders::_5tail; + using sprout::placeholders::_6tail; + using sprout::placeholders::_7tail; + using sprout::placeholders::_8tail; + using sprout::placeholders::_9tail; + using sprout::placeholders::_10tail; + using sprout::placeholders::_11tail; + using sprout::placeholders::_12tail; + using sprout::placeholders::_13tail; + using sprout::placeholders::_14tail; + using sprout::placeholders::_15tail; + using sprout::placeholders::_16tail; + using sprout::placeholders::_17tail; + using sprout::placeholders::_18tail; + using sprout::placeholders::_19tail; + using sprout::placeholders::_20tail; + using sprout::placeholders::_21tail; + using sprout::placeholders::_22tail; + using sprout::placeholders::_23tail; + using sprout::placeholders::_24tail; + using sprout::placeholders::_25tail; + using sprout::placeholders::_26tail; + using sprout::placeholders::_27tail; + using sprout::placeholders::_28tail; + using sprout::placeholders::_29tail; + using sprout::placeholders::_30tail; + // // is_placeholder // @@ -95,6 +163,10 @@ namespace sprout { struct is_placeholder : public std::integral_constant {}; + template + struct is_placeholder > + : public std::integral_constant + {}; template struct is_placeholder : public sprout::is_placeholder @@ -107,10 +179,6 @@ namespace sprout { struct is_placeholder : public sprout::is_placeholder {}; - template - struct is_placeholder > - : public std::integral_constant - {}; } // namespace sprout #endif // #ifndef SPROUT_FUNCTIONAL_BIND_PLACEHOLDER_HPP