diff options
| author | Dennis Brentjes <d.brentjes@gmail.com> | 2014-04-18 18:30:52 +0200 |
|---|---|---|
| committer | Dennis Brentjes <d.brentjes@gmail.com> | 2014-04-18 18:30:52 +0200 |
| commit | d834eba65c2c65c1540d13c9c39ced51bd87cf83 (patch) | |
| tree | 68c0533b668545cbfb0b0d556ac7ebf9bf8d3e97 /fusion_static_dispatch.hpp | |
| parent | 0969e7a24c0ae2a0cc9c5bd4be0d18c29bfe7f30 (diff) | |
| download | generic-gui-d834eba65c2c65c1540d13c9c39ced51bd87cf83.tar.gz generic-gui-d834eba65c2c65c1540d13c9c39ced51bd87cf83.tar.bz2 generic-gui-d834eba65c2c65c1540d13c9c39ced51bd87cf83.zip | |
First working prototype
Diffstat (limited to 'fusion_static_dispatch.hpp')
| -rw-r--r-- | fusion_static_dispatch.hpp | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/fusion_static_dispatch.hpp b/fusion_static_dispatch.hpp new file mode 100644 index 0000000..17b6ff4 --- /dev/null +++ b/fusion_static_dispatch.hpp @@ -0,0 +1,127 @@ +#pragma once + +#include "index_list.hpp" +#include "friendly_fusion.hpp" + +#include <boost/any.hpp> + +template <typename T, int index> +struct TypeAt { + typedef friendly_fusion::result_of::begin<T> begin; + 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; +}; + +#if defined( __GNUC__ ) && !defined( __clang__ ) +template<int index, typename T> +std::function<boost::any(T)> make_at_c_lambda(T seq) +{ + return [](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...>) +{ + 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); +} + +template<typename T> +struct get_nth_functor +{ + boost::any operator()(T seq, int index) + { + typedef typename friendly_fusion::result_of::size<T>::type seq_size; + typedef typename build_indices<seq_size::value>::type indices_type; + + return get_nth_impl(seq, index, indices_type{}); + } +}; + +template <typename T> +boost::any get_nth(T x, int index) +{ + return get_nth_functor<T>()(x, index); +} + +#if defined( __GNUC__ ) && !defined( __clang__ ) +template<int index, typename T> +std::function<std::string()> make_struct_member_name_lambda() +{ + return []{ + 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 { + + get_nth_name_impl() = default; + + template<int... Indices> + std::string operator()(int index, indices<Indices...>) + { + 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](); + } +}; + +template <typename T> +struct get_nth_name_functor +{ + std::string operator()(int index) + { + typedef typename friendly_fusion::result_of::size<T>::type seq_size; + typedef typename build_indices<seq_size::value>::type indices_type; + + return get_nth_name_impl<T>()(index, indices_type{}); + } +}; + +template <typename T, typename U> +struct get_nth_name_functor<boost::fusion::joint_view<T,U>> +{ + std::string operator()(int index) + { + constexpr size_t size_of_T = friendly_fusion::result_of::size<T>::type::value; + if(index < size_of_T){ + return get_nth_name_functor<T>()(index); + } else { + return get_nth_name_functor<U>()(index - size_of_T); + } + } +}; + +template <typename T> +std::string get_nth_name(int index) +{ + return get_nth_name_functor<T>()(index); +} |
