/** rjp++ Copyright (C) 2020 rexy712 This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef RJP_DISPATCH_HPP #define RJP_DISPATCH_HPP #include "rjp_internal.hpp" #include //is_same, true_type, false_type #include //forward #include namespace rjp{ class missing_dispatch_handler : public std::exception { public: const char* what(void)const noexcept override{ return "Argument not handled in rjp::dispatch"; } }; 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 struct has_operator_for{ template()(std::declval()))> static std::true_type check(U*); static std::false_type check(...); static constexpr bool value = std::is_same::value; }; template struct has_operator_for_any{ static constexpr bool value = has_operator_for::value || has_operator_for_any::value; }; template struct has_operator_for_any{ static constexpr bool value = has_operator_for::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)); } throw missing_dispatch_handler{}; //deals with -Wreturn-type warnings } } 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::value,void>::type* = nullptr> decltype(auto) operator()(const value&)const{} }; template dispatcher(Ts&&...) -> dispatcher; } #endif