That
struct JSONValue {
std::optional<std::string> string;
std::optional<double> number;
std::optional<bool> boolean;
std::optional<std::vector<JSONValue>> array;
std::optional<std::map<std::string, JSONValue>> object;
JSONValueType type;
};
really ought to be a variant, that would simplify things a lot. It'd just be
struct JSONValue;
using variant_type =
std::variant<
std::string
, double
, bool
, std::vector<JSONValue>
, std::map<std::string, JSONValue>
>;
struct JSONValue : variant_type {
using variant::variant;
};
then instead of switches you'd do:
std::string_view print_type(const variant_type& jtt) {
using namespace std::literals;
struct {
auto operator()(const std::string&) const noexcept { return "String"sv; }
auto operator()(double) const noexcept { return "Number"sv; }
auto operator()(bool) const noexcept { return "Bool"sv; }
auto operator()(const std::vector<JSONValue>&) const noexcept { return "Array"sv; }
auto operator()(const std::map<std::string, JSONValue>&) const noexcept { return "Dict"sv; }
auto operator()(std::monostate) const noexcept { return "Null"sv; }
} vis;
return std::visit(vis, jtt);
}
which is much safer than switch/cases