Last active
June 27, 2020 23:12
-
-
Save qookei/99e849acbf2c4f80912e3d8f301e4042 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Requires compiler with C++20 concept support (GCC 10.1/Clang 10 or newer) | |
*/ | |
#include <unordered_map> | |
#include <concepts> | |
#include <iostream> | |
#include <variant> | |
#include <string> | |
#include <vector> | |
template <typename ...Ts> | |
struct json_array { | |
std::tuple<Ts...> values; | |
}; | |
template <typename T> | |
struct json_member { | |
using value_type = T; | |
std::string name; | |
T value; | |
}; | |
template <typename ...Ts> | |
using json_object = json_array<json_member<Ts>...>; | |
template <typename ...Ts> | |
auto make_object(Ts &&...args) { | |
return json_object<typename Ts::value_type...>{std::make_tuple(args...)}; | |
} | |
template <typename ...Ts> | |
auto make_array(Ts &&...args) { | |
return json_array<Ts...>{std::make_tuple(args...)}; | |
} | |
template <typename T> | |
auto make_member(const std::string &name, T &&arg) { | |
return json_member<T>{name, std::forward<T>(arg)}; | |
} | |
struct { | |
template <typename T, typename ...Ts> | |
std::string operator()(const Ts &...ts, const T &t) { | |
return (*this)(ts...) + "," + (*this)(t); | |
} | |
std::string operator()() { | |
return ""; | |
} | |
template <typename T> | |
std::string operator()(const json_member<T> &t) { | |
return (t.name.size() ? "\"" + t.name + "\":" : "") + (*this)(t.value); | |
} | |
template <size_t ...I, typename T_> | |
std::string group_helper_(const T_ &t, std::index_sequence<I...>) { | |
auto f = [&]<typename T>(const T &t) { | |
return (*this)(t) + ","; | |
}; | |
return "" + (f(std::get<I>(t.values)) + ...); | |
} | |
template <typename T> | |
std::string group_helper_(const T &, std::index_sequence<>) { | |
return ""; | |
} | |
template <typename ...Ts> | |
std::string operator()(const json_object<Ts...> &t) { | |
return "{" + group_helper_(t, std::make_index_sequence<sizeof...(Ts) - 1>{}) | |
+ (*this)(std::get<sizeof...(Ts) - 1>(t.values)) + "}"; | |
} | |
template <typename ...Ts> | |
std::string operator()(const json_array<Ts...> &t) { | |
return "[" + group_helper_(t, std::make_index_sequence<sizeof...(Ts) - 1>{}) | |
+ (*this)(std::get<sizeof...(Ts) - 1>(t.values)) + "]"; | |
} | |
template <typename T> | |
std::string operator()(const T &t) requires (std::integral<T> || std::floating_point<T>) { | |
return std::to_string(t); | |
} | |
std::string operator()(const std::string &t) { | |
return "\"" + t + "\""; | |
} | |
} make_json_repr_impl_; | |
template <typename ...Args> | |
std::string make_json_repr(Args &&...args) { | |
return make_json_repr_impl_(std::forward<Args>(args)...); | |
} | |
int main() { | |
using namespace std::string_literals; | |
std::cout << make_json_repr( | |
make_object( | |
make_member("foo", 123.), | |
make_member("bar", "hello"s), | |
make_member("baz", make_array(1, 2, "fizz"s, 4)), | |
make_member("bif", make_object( | |
make_member("baf", 1), | |
make_member("bag", make_array("buzz"s, "fizz"s, 7, 8)) | |
)) | |
) | |
) << std::endl; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment