#pragma once #include "index_list.hpp" #include "friendly_fusion.hpp" #include #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; } ... }; return table[index](); } template bool is_const(int index) { typedef typename friendly_fusion::result_of::size::type seq_size; typedef typename build_indices::type indices_type; return is_const_impl(index, indices_type{}); } template std::function make_at_c_lambda(T seq) { return [](T seq){ return boost::any(friendly_fusion::deref(friendly_fusion::advance_c(friendly_fusion::begin(seq)))); }; } template boost::any get_nth_impl(T seq, int index, indices) { typedef std::function element_type; static element_type table[] = { make_at_c_lambda(seq) ... }; return table[index](seq); } 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; return get_nth_impl(seq, index, indices_type{}); } }; template boost::any get_nth(T x, int index) { return get_nth_functor()(x, index); } template typename std::enable_if::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 typename std::enable_if::type assign(T& lh, V rh) { lh = rh; } template std::function make_set_nth_lambda() { return [](T& seq, 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::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{}); } }; template void set_nth(T& x, int index, boost::any const& value) { set_nth_functor()(x, index, 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; return get_nth_name_impl()(index, indices_type{}); } }; template struct get_nth_name_functor> { std::string operator()(int index) { constexpr size_t size_of_T = friendly_fusion::result_of::size::type::value; if(index < size_of_T){ return get_nth_name_functor()(index); } else { return get_nth_name_functor()(index - size_of_T); } } }; template std::string get_nth_name(int index) { return get_nth_name_functor()(index); }