summaryrefslogtreecommitdiff
path: root/fusion_static_dispatch.hpp
diff options
context:
space:
mode:
authorDennis Brentjes <d.brentjes@gmail.com>2014-04-18 18:30:52 +0200
committerDennis Brentjes <d.brentjes@gmail.com>2014-04-18 18:30:52 +0200
commitd834eba65c2c65c1540d13c9c39ced51bd87cf83 (patch)
tree68c0533b668545cbfb0b0d556ac7ebf9bf8d3e97 /fusion_static_dispatch.hpp
parent0969e7a24c0ae2a0cc9c5bd4be0d18c29bfe7f30 (diff)
downloadgeneric-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.hpp127
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);
+}