From d4ea872acfee5d4bf563334181400a9fef7d5add Mon Sep 17 00:00:00 2001 From: Dennis Brentjes Date: Mon, 19 May 2014 15:48:23 +0200 Subject: Reworked the Fusion_static_dispatch to be more generic. --- fusion_static_dispatch.hpp | 185 +++++++++++++++++++-------------------------- 1 file changed, 79 insertions(+), 106 deletions(-) diff --git a/fusion_static_dispatch.hpp b/fusion_static_dispatch.hpp index 9240cc2..6b3ad42 100644 --- a/fusion_static_dispatch.hpp +++ b/fusion_static_dispatch.hpp @@ -8,71 +8,87 @@ #include #include -template -bool is_const_impl(int index, indices) -{ - typedef std::function element_type; - static element_type table[] = { - [] { - typedef friendly_fusion::result_of::begin begin; - typedef friendly_fusion::result_of::advance_c adv_it; - typedef friendly_fusion::result_of::deref deref; - typedef std::remove_reference unreferenced_type; - - return std::is_const::value; - } +template +struct IndicesOf +{ + typedef typename build_indices::type::value>::type type; +}; + +template class F, int... Indices, typename... Args> +typename F::return_type apply_functor_to_member_impl(indices, int index, Args... args) +{ + typedef std::function::return_type(Args...)> f_type; + static f_type array[] = { + (std::function::return_type(Args...)>) F::template call ... }; - return table[index](); + return array[index](std::forward(args)...); } -template -bool is_const(int index) +template class F, int... Indices, typename Arg1, typename... Args> +typename F::return_type apply_functor_to_member_impl(indices, int index, Arg1& arg1, Args... args) { - typedef typename friendly_fusion::result_of::size::type seq_size; - typedef typename build_indices::type indices_type; + typedef std::function::return_type(Arg1&, Args...)> f_type; + static f_type array[] = { + (std::function::return_type(Arg1&, Args...)>) F::template call + ... + }; - return is_const_impl(index, indices_type{}); + return array[index](arg1, std::forward(args)...); } -template -std::function make_at_c_lambda(T seq) +template class F, typename... Args> +typename F::return_type apply_functor_to_member(int index, Args... args) { - return [](T seq){ - return boost::any(friendly_fusion::deref(friendly_fusion::advance_c(friendly_fusion::begin(seq)))); - }; + return apply_functor_to_member_impl(typename IndicesOf::type{}, index, std::forward(args)...); +} + +template class F, typename Arg1, typename... Args> +typename F::return_type apply_functor_to_member(int index, Arg1& arg1, Args... args) +{ + return apply_functor_to_member_impl(typename IndicesOf::type{}, index, arg1, std::forward(args)...); } -template -boost::any get_nth_impl(T seq, int index, indices) +template +struct is_const_functor { - typedef std::function element_type; - static element_type table[] = + typedef bool return_type; + + template + static return_type call() { - make_at_c_lambda(seq) - ... - }; + typedef friendly_fusion::result_of::begin begin; + typedef friendly_fusion::result_of::advance_c adv_it; + typedef friendly_fusion::result_of::deref deref; + typedef std::remove_reference unreferenced_type; + + return std::is_const::value; + } +}; - return table[index](seq); +template +bool is_const(int index) +{ + return apply_functor_to_member(index); } -template +template struct get_nth_functor { - boost::any operator()(T seq, int index) - { - typedef typename friendly_fusion::result_of::size::type seq_size; - typedef typename build_indices::type indices_type; + typedef boost::any return_type; - return get_nth_impl(seq, index, indices_type{}); + template + static return_type call(T& seq) + { + return boost::any(friendly_fusion::deref(friendly_fusion::advance_c(friendly_fusion::begin(seq)))); } }; template boost::any get_nth(T x, int index) { - return get_nth_functor()(x, index); + return apply_functor_to_member(index, x); } template @@ -89,99 +105,56 @@ typename std::enable_if::type assign(T& lh, V rh) lh = rh; } -template -std::function make_set_nth_lambda() + +template +struct set_nth_functor { - return [](T& seq, boost::any const& value){ + typedef void return_type; + + template + static return_type call(T& t, boost::any const& value) + { typedef friendly_fusion::result_of::begin begin; - typedef friendly_fusion::result_of::advance_c adv_it; + typedef friendly_fusion::result_of::advance_c adv_it; typedef friendly_fusion::result_of::deref deref; typedef typename std::decay::type value_type; typedef typename std::remove_reference::type unreferenced_type; - assign::value>(friendly_fusion::deref(friendly_fusion::advance_c(friendly_fusion::begin(seq))), boost::any_cast(value)); - }; -} - -template -void set_nth_impl(T& seq, int index, boost::any const& value, indices) -{ - typedef std::function element_type; - static element_type table[] = - { - make_set_nth_lambda() - ... - }; - - table[index](seq, value); -} - -template -struct set_nth_functor -{ - void operator()(T& seq, int index, boost::any const& value) - { - typedef typename friendly_fusion::result_of::size::type seq_size; - typedef typename build_indices::type indices_type; - - set_nth_impl(seq, index, value, indices_type{}); + assign::value>(friendly_fusion::deref(friendly_fusion::advance_c(friendly_fusion::begin(t))), boost::any_cast(value)); } }; template void set_nth(T& x, int index, boost::any const& value) { - set_nth_functor()(x, index, value); + apply_functor_to_member(index, x, value); } -template -std::function make_struct_member_name_lambda() -{ - return []{ - return std::string(friendly_fusion::extension::struct_member_name::call()); - }; -} -template -struct get_nth_name_impl { - - get_nth_name_impl() = default; - - template - std::string operator()(int index, indices) - { - typedef std::function element_type; - static element_type table[] = { - //Workaround for gcc bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47226 - make_struct_member_name_lambda() - ... - }; - - return table[index](); - } -}; - template struct get_nth_name_functor { - std::string operator()(int index) - { - typedef typename friendly_fusion::result_of::size::type seq_size; - typedef typename build_indices::type indices_type; + typedef std::string return_type; - return get_nth_name_impl()(index, indices_type{}); + template + static return_type call() + { + return std::string(friendly_fusion::extension::struct_member_name::call()); } }; template struct get_nth_name_functor> { - std::string operator()(int index) + typedef std::string return_type; + + template + static return_type call() { constexpr size_t size_of_T = friendly_fusion::result_of::size::type::value; - if(index < size_of_T){ - return get_nth_name_functor()(index); + if(I < size_of_T){ + return apply_functor_to_member(I); } else { - return get_nth_name_functor()(index - size_of_T); + return apply_functor_to_member(I); } } }; @@ -189,5 +162,5 @@ struct get_nth_name_functor> template std::string get_nth_name(int index) { - return get_nth_name_functor()(index); + return apply_functor_to_member(index); } -- cgit v1.2.3-70-g09d2