#ifndef RJP_DISPATCH_HPP #define RJP_DISPATCH_HPP #include "rjp_internal.hpp" #include //is_same, true_type, false_type #include //forward namespace rjp{ namespace detail{ template struct to_value_type; template<> struct to_value_type{ using type = rjp::object; }; template<> struct to_value_type{ using type = rjp::string_val; }; template<> struct to_value_type{ using type = rjp::integer; }; template<> struct to_value_type{ using type = rjp::dfloat; }; template<> struct to_value_type{ using type = rjp::boolean; }; template<> struct to_value_type{ using type = rjp::array; }; template<> struct to_value_type{ using type = rjp::null; }; template using to_value_type_t = typename to_value_type::type; template struct next_data_type; template<> struct next_data_type{ static constexpr RJP_data_type value = rjp_json_string; }; template<> struct next_data_type{ static constexpr RJP_data_type value = rjp_json_integer; }; template<> struct next_data_type{ static constexpr RJP_data_type value = rjp_json_dfloat; }; template<> struct next_data_type{ static constexpr RJP_data_type value = rjp_json_boolean; }; template<> struct next_data_type{ static constexpr RJP_data_type value = rjp_json_array; }; template<> struct next_data_type{ static constexpr RJP_data_type value = rjp_json_null; }; template struct has_next_data_type_helper{ template static std::true_type check(U*); static std::false_type check(...); static constexpr bool value = std::is_same*)0))>::value; }; template struct has_next_data_type{ static constexpr bool value = has_next_data_type_helper::value; }; template decltype(auto) dispatch_helper(Func&& fun, Val&& v){ if(v.type() == T){ return std::forward(fun)(static_cast>(std::forward(v))); } if constexpr(detail::has_next_data_type::value){ return dispatch_helper::value>(std::forward(fun), std::forward(v)); } } } template decltype(auto) dispatch(Func&& fun, Val&& v){ return detail::dispatch_helper(std::forward(fun), std::forward(v)); } template struct dispatcher : public Ts... { using Ts::operator()...; }; template dispatcher(Ts&&...) -> dispatcher; } #endif