diff options
Diffstat (limited to 'fusion_static_dispatch.hpp')
| -rw-r--r-- | fusion_static_dispatch.hpp | 79 |
1 files changed, 46 insertions, 33 deletions
diff --git a/fusion_static_dispatch.hpp b/fusion_static_dispatch.hpp index ce81c90..9240cc2 100644 --- a/fusion_static_dispatch.hpp +++ b/fusion_static_dispatch.hpp @@ -6,8 +6,36 @@ #include <boost/any.hpp> #include <functional> +#include <iostream> + +template <typename T, int... Indices> +bool is_const_impl(int index, indices<Indices...>) +{ + typedef std::function<bool()> element_type; + static element_type table[] = { + [] { + typedef friendly_fusion::result_of::begin<T> begin; + typedef friendly_fusion::result_of::advance_c<typename begin::type, Indices> adv_it; + typedef friendly_fusion::result_of::deref<typename adv_it::type> deref; + typedef std::remove_reference<typename deref::type> unreferenced_type; + + return std::is_const<typename unreferenced_type::type>::value; + } + ... + }; + + return table[index](); +} + +template <typename T> +bool is_const(int index) +{ + typedef typename friendly_fusion::result_of::size<T>::type seq_size; + typedef typename build_indices<seq_size::value>::type indices_type; + + return is_const_impl<T>(index, indices_type{}); +} -#if defined( __GNUC__ ) && !defined( __clang__ ) template<int index, typename T> std::function<boost::any(T)> make_at_c_lambda(T seq) { @@ -15,7 +43,6 @@ std::function<boost::any(T)> make_at_c_lambda(T seq) return boost::any(friendly_fusion::deref(friendly_fusion::advance_c<index>(friendly_fusion::begin(seq)))); }; } -#endif //defined( __GNUC__ ) && !defined( __clang__ ) template<typename T, int... Indices> boost::any get_nth_impl(T seq, int index, indices<Indices...>) @@ -23,14 +50,8 @@ boost::any get_nth_impl(T seq, int index, indices<Indices...>) typedef std::function<boost::any(T)> element_type; static element_type table[] = { -#if defined( __GNUC__ ) && !defined( __clang__ ) - //Workaround for gcc bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47226 make_at_c_lambda<Indices>(seq) ... -#else - [](T seq){return boost::any(friendly_fusion::deref(friendly_fusion::advance_c<Indices>(friendly_fusion::begin(seq))));} - ... -#endif //defined( __GNUC__ ) && !defined( __clang__ ) }; return table[index](seq); @@ -54,7 +75,20 @@ boost::any get_nth(T x, int index) return get_nth_functor<T>()(x, index); } -#if defined( __GNUC__ ) && !defined( __clang__ ) +template <bool b, typename T, typename V> +typename std::enable_if<b, void>::type assign(T&, V) +{ + //this function will never be called, but has to be defined. + //We need to generate a assign statement for all members at compile time even when they are const. + return; +} + +template <bool b, typename T, typename V> +typename std::enable_if<!b, void>::type assign(T& lh, V rh) +{ + lh = rh; +} + template<int index, typename T> std::function<void(T&, boost::any const&)> make_set_nth_lambda() { @@ -63,11 +97,11 @@ std::function<void(T&, boost::any const&)> make_set_nth_lambda() typedef friendly_fusion::result_of::advance_c<typename begin::type, index> adv_it; typedef friendly_fusion::result_of::deref<typename adv_it::type> deref; typedef typename std::decay<typename deref::type>::type value_type; + typedef typename std::remove_reference<typename deref::type>::type unreferenced_type; - friendly_fusion::deref(friendly_fusion::advance_c<index>(friendly_fusion::begin(seq))) = boost::any_cast<value_type>(value); + assign<std::is_const<unreferenced_type>::value>(friendly_fusion::deref(friendly_fusion::advance_c<index>(friendly_fusion::begin(seq))), boost::any_cast<value_type>(value)); }; } -#endif //defined( __GNUC__ ) && !defined( __clang__ ) template <typename T, int... Indices> void set_nth_impl(T& seq, int index, boost::any const& value, indices<Indices...>) @@ -75,21 +109,8 @@ void set_nth_impl(T& seq, int index, boost::any const& value, indices<Indices... typedef std::function<void(T&, boost::any const&)> element_type; static element_type table[] = { - #if defined( __GNUC__ ) && !defined( __clang__ ) - make_set_nth_lambda<Indices, T>() - ... - #else - [](T& seq, boost::any const& value) - { - typedef friendly_fusion::result_of::begin<T> begin; - typedef friendly_fusion::result_of::advance_c<typename begin::type, Indices> adv_it; - typedef friendly_fusion::result_of::deref<typename adv_it::type> deref; - typedef typename std::decay<typename deref::type>::type value_type; - - friendly_fusion::deref(friendly_fusion::advance_c<Indices>(friendly_fusion::begin(seq))) = boost::any_cast<value_type>(value); - } + make_set_nth_lambda<Indices, T>() ... - #endif //defined( __GNUC__ ) && !defined( __clang__ ) }; table[index](seq, value); @@ -113,7 +134,6 @@ void set_nth(T& x, int index, boost::any const& value) set_nth_functor<T>()(x, index, value); } -#if defined( __GNUC__ ) && !defined( __clang__ ) template<int index, typename T> std::function<std::string()> make_struct_member_name_lambda() { @@ -121,8 +141,6 @@ std::function<std::string()> make_struct_member_name_lambda() return std::string(friendly_fusion::extension::struct_member_name<T, index>::call()); }; } -#endif //defined( __GNUC__ ) && !defined( __clang__ ) - template<typename T> struct get_nth_name_impl { @@ -133,14 +151,9 @@ struct get_nth_name_impl { { typedef std::function<std::string()> element_type; static element_type table[] = { - #if defined( __GNUC__ ) && !defined( __clang__ ) //Workaround for gcc bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47226 make_struct_member_name_lambda<Indices, T>() ... - #else - []{return std::string(friendly_fusion::extension::struct_member_name<T, Indices>::call());} - ... - #endif //defined( __GNUC__ ) && !defined( __clang__ ) }; return table[index](); |
