#pragma once #include "index_list.hpp" #include "friendly_fusion.hpp" #include #include #if defined( __GNUC__ ) && !defined( __clang__ ) 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)))); }; } #endif //defined( __GNUC__ ) && !defined( __clang__ ) template boost::any get_nth_impl(T seq, int index, indices) { typedef std::function 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(seq) ... #else [](T seq){return boost::any(friendly_fusion::deref(friendly_fusion::advance_c(friendly_fusion::begin(seq))));} ... #endif //defined( __GNUC__ ) && !defined( __clang__ ) }; 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); } #if defined( __GNUC__ ) && !defined( __clang__ ) 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; friendly_fusion::deref(friendly_fusion::advance_c(friendly_fusion::begin(seq))) = boost::any_cast(value); }; } #endif //defined( __GNUC__ ) && !defined( __clang__ ) template void set_nth_impl(T& seq, int index, boost::any const& value, indices) { typedef std::function element_type; static element_type table[] = { #if defined( __GNUC__ ) && !defined( __clang__ ) make_set_nth_lambda() ... #else [](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; friendly_fusion::deref(friendly_fusion::advance_c(friendly_fusion::begin(seq))) = boost::any_cast(value); } ... #endif //defined( __GNUC__ ) && !defined( __clang__ ) }; 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); } #if defined( __GNUC__ ) && !defined( __clang__ ) template std::function make_struct_member_name_lambda() { return []{ return std::string(friendly_fusion::extension::struct_member_name::call()); }; } #endif //defined( __GNUC__ ) && !defined( __clang__ ) 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[] = { #if defined( __GNUC__ ) && !defined( __clang__ ) //Workaround for gcc bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47226 make_struct_member_name_lambda() ... #else []{return std::string(friendly_fusion::extension::struct_member_name::call());} ... #endif //defined( __GNUC__ ) && !defined( __clang__ ) }; 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); }