Skip to content

Commit

Permalink
Add restriction for tuple specialization of to_json
Browse files Browse the repository at this point in the history
This commit fix the issue #1825

Signed-off-by: Camille Bégué <c.begue@samsung.com>
  • Loading branch information
Camille Bégué committed Nov 4, 2019
1 parent 3790bd9 commit 8b686b3
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 6 deletions.
6 changes: 3 additions & 3 deletions include/nlohmann/detail/conversions/to_json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,10 +322,10 @@ 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)
template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
void to_json(BasicJsonType& j, const T& t)
{
to_json_tuple_impl(j, t, index_sequence_for<Args...> {});
to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
}

struct to_json_fn
Expand Down
13 changes: 13 additions & 0 deletions include/nlohmann/detail/meta/type_traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -357,5 +357,18 @@ struct is_compatible_type_impl <
template <typename BasicJsonType, typename CompatibleType>
struct is_compatible_type
: is_compatible_type_impl<BasicJsonType, CompatibleType> {};

// https://en.cppreference.com/w/cpp/types/conjunction
template<class...> struct conjunction : std::true_type { };
template<class B1> struct conjunction<B1> : B1 { };
template<class B1, class... Bn>
struct conjunction<B1, Bn...>
: std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};

template <typename T1, typename T2>
struct is_constructible_tuple : std::false_type {};

template <typename T1, typename... Args>
struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<std::is_constructible<T1, Args>...> {};
} // namespace detail
} // namespace nlohmann
19 changes: 16 additions & 3 deletions single_include/nlohmann/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2794,6 +2794,19 @@ struct is_compatible_type_impl <
template <typename BasicJsonType, typename CompatibleType>
struct is_compatible_type
: is_compatible_type_impl<BasicJsonType, CompatibleType> {};

// https://en.cppreference.com/w/cpp/types/conjunction
template<class...> struct conjunction : std::true_type { };
template<class B1> struct conjunction<B1> : B1 { };
template<class B1, class... Bn>
struct conjunction<B1, Bn...>
: std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};

template <typename T1, typename T2>
struct is_constructible_tuple : std::false_type {};

template <typename T1, typename... Args>
struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<std::is_constructible<T1, Args>...> {};
} // namespace detail
} // namespace nlohmann

Expand Down Expand Up @@ -3753,10 +3766,10 @@ 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)
template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
void to_json(BasicJsonType& j, const T& t)
{
to_json_tuple_impl(j, t, index_sequence_for<Args...> {});
to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
}

struct to_json_fn
Expand Down
6 changes: 6 additions & 0 deletions test/src/unit-regression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1842,6 +1842,12 @@ TEST_CASE("regression tests")
static_assert(!std::is_constructible<json, std::pair<NotSerializableData, std::string>>::value, "");
static_assert(std::is_constructible<json, std::pair<int, std::string>>::value, "");
}
SECTION("issue #1825 - A tuple<Args..> is json constructible only if all T in Args are json constructible")
{
static_assert(!std::is_constructible<json, std::tuple<std::string, NotSerializableData>>::value, "");
static_assert(!std::is_constructible<json, std::tuple<NotSerializableData, std::string>>::value, "");
static_assert(std::is_constructible<json, std::tuple<int, std::string>>::value, "");
}
}

#if not defined(JSON_NOEXCEPTION)
Expand Down

0 comments on commit 8b686b3

Please sign in to comment.