/**
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 "object.hpp"
#include "integral.hpp"
#include "array.hpp"
#include "value.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