summaryrefslogtreecommitdiff
path: root/fusion_static_dispatch.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'fusion_static_dispatch.hpp')
-rw-r--r--fusion_static_dispatch.hpp79
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]();