add pair/tuple conversions
This commit is contained in:
parent
c98364834f
commit
6e4910d5c5
2 changed files with 121 additions and 0 deletions
69
src/json.hpp
69
src/json.hpp
|
@ -465,6 +465,39 @@ using enable_if_t = typename std::enable_if<B, T>::type;
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
|
using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
|
||||||
|
|
||||||
|
// implementation of C++14 index_sequence and affiliates
|
||||||
|
// source: https://stackoverflow.com/a/32223343
|
||||||
|
template <std::size_t... Ints>
|
||||||
|
struct index_sequence
|
||||||
|
{
|
||||||
|
using type = index_sequence;
|
||||||
|
using value_type = std::size_t;
|
||||||
|
static constexpr std::size_t size() noexcept
|
||||||
|
{
|
||||||
|
return sizeof...(Ints);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Sequence1, class Sequence2>
|
||||||
|
struct merge_and_renumber;
|
||||||
|
|
||||||
|
template <std::size_t... I1, std::size_t... I2>
|
||||||
|
struct merge_and_renumber<index_sequence<I1...>, index_sequence<I2...>>
|
||||||
|
: index_sequence < I1..., (sizeof...(I1) + I2)... >
|
||||||
|
{ };
|
||||||
|
|
||||||
|
template <std::size_t N>
|
||||||
|
struct make_index_sequence
|
||||||
|
: merge_and_renumber < typename make_index_sequence < N / 2 >::type,
|
||||||
|
typename make_index_sequence < N - N / 2 >::type >
|
||||||
|
{ };
|
||||||
|
|
||||||
|
template<> struct make_index_sequence<0> : index_sequence<> { };
|
||||||
|
template<> struct make_index_sequence<1> : index_sequence<0> { };
|
||||||
|
|
||||||
|
template<typename... Ts>
|
||||||
|
using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Implementation of two C++17 constructs: conjunction, negation. This is needed
|
Implementation of two C++17 constructs: conjunction, negation. This is needed
|
||||||
to avoid evaluating all the traits in a condition
|
to avoid evaluating all the traits in a condition
|
||||||
|
@ -866,6 +899,24 @@ void to_json(BasicJsonType& j, T (&arr)[N])
|
||||||
external_constructor<value_t::array>::construct(j, arr);
|
external_constructor<value_t::array>::construct(j, arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename BasicJsonType, typename... Args>
|
||||||
|
void to_json(BasicJsonType& j, const std::pair<Args...>& p)
|
||||||
|
{
|
||||||
|
j = {p.first, p.second};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename BasicJsonType, typename Tuple, std::size_t... Idx>
|
||||||
|
void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...>)
|
||||||
|
{
|
||||||
|
j = {std::get<Idx>(t)...};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename BasicJsonType, typename... Args>
|
||||||
|
void to_json(BasicJsonType& j, const std::tuple<Args...>& t)
|
||||||
|
{
|
||||||
|
to_json_tuple_impl(j, t, index_sequence_for<Args...> {});
|
||||||
|
}
|
||||||
|
|
||||||
///////////////
|
///////////////
|
||||||
// from_json //
|
// from_json //
|
||||||
///////////////
|
///////////////
|
||||||
|
@ -1094,6 +1145,24 @@ void from_json(const BasicJsonType& j, ArithmeticType& val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename BasicJsonType, typename... Args>
|
||||||
|
void from_json(const BasicJsonType& j, std::pair<Args...>& p)
|
||||||
|
{
|
||||||
|
p = {j.at(0), j.at(1)};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename BasicJsonType, typename Tuple, std::size_t... Idx>
|
||||||
|
void from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence<Idx...>)
|
||||||
|
{
|
||||||
|
t = std::make_tuple(j.at(Idx)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename BasicJsonType, typename... Args>
|
||||||
|
void from_json(const BasicJsonType& j, std::tuple<Args...>& t)
|
||||||
|
{
|
||||||
|
from_json_tuple_impl(j, t, index_sequence_for<Args...> {});
|
||||||
|
}
|
||||||
|
|
||||||
struct to_json_fn
|
struct to_json_fn
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -239,6 +239,58 @@ TEST_CASE("constructors")
|
||||||
CHECK(j == j_reference);
|
CHECK(j == j_reference);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("std::pair")
|
||||||
|
{
|
||||||
|
std::pair<float, std::string> p{1.0, "string"};
|
||||||
|
json j(p);
|
||||||
|
|
||||||
|
CHECK(j.type() == json::value_t::array);
|
||||||
|
REQUIRE(j.size() == 2);
|
||||||
|
CHECK(j[0] == std::get<0>(p));
|
||||||
|
CHECK(j[1] == std::get<1>(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("std::pair with discarded values")
|
||||||
|
{
|
||||||
|
json j{1, 2.0, "string"};
|
||||||
|
|
||||||
|
const auto p = j.get<std::pair<int, float>>();
|
||||||
|
CHECK(p.first == j[0]);
|
||||||
|
CHECK(p.second == j[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("std::tuple")
|
||||||
|
{
|
||||||
|
const auto t = std::make_tuple(1.0, "string", 42, std::vector<int> {0, 1});
|
||||||
|
json j(t);
|
||||||
|
|
||||||
|
CHECK(j.type() == json::value_t::array);
|
||||||
|
REQUIRE(j.size() == 4);
|
||||||
|
CHECK(j[0] == std::get<0>(t));
|
||||||
|
CHECK(j[1] == std::get<1>(t));
|
||||||
|
CHECK(j[2] == std::get<2>(t));
|
||||||
|
CHECK(j[3][0] == 0);
|
||||||
|
CHECK(j[3][1] == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("std::tuple with discarded values")
|
||||||
|
{
|
||||||
|
json j{1, 2.0, "string", 42};
|
||||||
|
|
||||||
|
const auto t = j.get<std::tuple<int, float, std::string>>();
|
||||||
|
CHECK(std::get<0>(t) == j[0]);
|
||||||
|
CHECK(std::get<1>(t) == j[1]);
|
||||||
|
CHECK(std::get<2>(t) == j[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("std::pair/tuple failures")
|
||||||
|
{
|
||||||
|
json j{1};
|
||||||
|
|
||||||
|
CHECK_THROWS((j.get<std::pair<int, int>>()));
|
||||||
|
CHECK_THROWS((j.get<std::tuple<int, int>>()));
|
||||||
|
}
|
||||||
|
|
||||||
SECTION("std::forward_list<json>")
|
SECTION("std::forward_list<json>")
|
||||||
{
|
{
|
||||||
std::forward_list<json> a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
|
std::forward_list<json> a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
|
||||||
|
|
Loading…
Reference in a new issue