mirror of
https://github.com/boostorg/leaf.git
synced 2026-02-17 13:52:14 +00:00
Better SFINAE in JSON encoders
This commit is contained in:
@@ -2873,8 +2873,9 @@ namespace serialization
|
||||
{
|
||||
boost::json::value & v_;
|
||||
|
||||
// Enabled if x is assignable to boost::json::value, or
|
||||
// if tag_invoke is defined for boost::json::value_from_tag.
|
||||
// Uses unspecified SFINAE expression designed to select this overload
|
||||
// only if no other compatible overload is found.
|
||||
// Implemented in terms of boost::json::value_from.
|
||||
template <class T>
|
||||
friend void output( boost_json_encoder &, T const & x );
|
||||
|
||||
@@ -2906,7 +2907,9 @@ namespace serialization
|
||||
{
|
||||
Json & j_;
|
||||
|
||||
// Enabled if to_json is available for Json and T.
|
||||
// Uses unspecified SFINAE expression designed to select this overload
|
||||
// only if no other compatible overload is found.
|
||||
// Implemented in terms of to_json.
|
||||
template <class T>
|
||||
friend void output( nlohmann_json_encoder &, T const & x );
|
||||
|
||||
@@ -3667,8 +3670,9 @@ namespace serialization
|
||||
{
|
||||
boost::json::value & v_;
|
||||
|
||||
// Enabled if x is assignable to boost::json::value, or
|
||||
// if tag_invoke is defined for boost::json::value_from_tag.
|
||||
// Uses unspecified SFINAE expression designed to select this overload
|
||||
// only if no other compatible overload is found.
|
||||
// Implemented in terms of boost::json::value_from.
|
||||
template <class T>
|
||||
friend void output( boost_json_encoder &, T const & x );
|
||||
|
||||
@@ -3680,10 +3684,7 @@ namespace serialization
|
||||
} }
|
||||
----
|
||||
|
||||
The `boost_json_encoder` type serializes error objects to JSON format using https://www.boost.org/doc/libs/release/libs/json/[Boost.JSON]. The `output` function is enabled for:
|
||||
|
||||
* Types directly assignable to `boost::json::value`
|
||||
* Types for which a `tag_invoke` overload for `value_from_tag` can be found via ADL
|
||||
The `boost_json_encoder` type serializes error objects to JSON format using https://www.boost.org/doc/libs/release/libs/json/[Boost.JSON]. The `output` function is implemented in terms of `boost::json::value_from`.
|
||||
|
||||
See <<tutorial-serialization>>.
|
||||
|
||||
@@ -4489,7 +4490,9 @@ namespace serialization
|
||||
{
|
||||
Json & j_;
|
||||
|
||||
// Enabled if to_json is available for Json and T.
|
||||
// Uses unspecified SFINAE expression designed to select this overload
|
||||
// only if no other compatible overload is found.
|
||||
// Implemented in terms of to_json.
|
||||
template <class T>
|
||||
friend void output( nlohmann_json_encoder &, T const & x );
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include <boost/leaf/config.hpp>
|
||||
#include <boost/leaf/detail/type_name.hpp>
|
||||
#include <boost/leaf/detail/function_traits.hpp>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
@@ -16,7 +18,10 @@ namespace serialization
|
||||
struct encoder_adl {};
|
||||
|
||||
template <class Encoder, class T>
|
||||
auto output(Encoder & e, T const & x) -> decltype(output(e, x.value))
|
||||
typename std::enable_if<
|
||||
sizeof(T) == sizeof(decltype(std::declval<T const &>().value)),
|
||||
decltype(output(std::declval<Encoder &>(), std::declval<T const &>().value), void())>::type
|
||||
output(Encoder & e, T const & x)
|
||||
{
|
||||
output(e, x.value);
|
||||
}
|
||||
|
||||
@@ -5,12 +5,15 @@
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost { namespace json {
|
||||
|
||||
class value;
|
||||
struct value_from_tag;
|
||||
|
||||
template <class T>
|
||||
void value_from(T &&, value &);
|
||||
|
||||
} }
|
||||
|
||||
@@ -18,21 +21,16 @@ namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
template <class Value = boost::json::value, class ValueFromTag = boost::json::value_from_tag>
|
||||
template <class Value = boost::json::value>
|
||||
struct boost_json_encoder_
|
||||
{
|
||||
Value & v_;
|
||||
|
||||
template <class T>
|
||||
friend auto output(boost_json_encoder_ & e, T const & x) -> decltype(std::declval<Value &>() = x, void())
|
||||
template <class Encoder, class T, class... Deprioritize>
|
||||
friend typename std::enable_if<std::is_same<Encoder, boost_json_encoder_>::value>::type
|
||||
output(Encoder & e, T const & x, Deprioritize...)
|
||||
{
|
||||
e.v_ = x;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
friend auto output(boost_json_encoder_ & e, T const & x) -> decltype(tag_invoke(std::declval<ValueFromTag>(), std::declval<Value &>(), x), void())
|
||||
{
|
||||
tag_invoke(ValueFromTag{}, e.v_, x);
|
||||
boost::json::value_from(x, e.v_);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
@@ -16,10 +17,12 @@ namespace serialization
|
||||
{
|
||||
Json & j_;
|
||||
|
||||
template <class T>
|
||||
friend auto output(nlohmann_json_encoder & e, T const & x) -> decltype(to_json(std::declval<Json &>(), x), void())
|
||||
template <class Encoder, class T, class... Deprioritize>
|
||||
friend typename std::enable_if<std::is_same<Encoder, nlohmann_json_encoder>::value, Json *>::type
|
||||
output(Encoder & e, T const & x, Deprioritize...)
|
||||
{
|
||||
to_json(e.j_, x);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#if BOOST_LEAF_CFG_STD_SYSTEM_ERROR
|
||||
# include <system_error>
|
||||
#endif
|
||||
@@ -76,6 +77,11 @@ struct my_error
|
||||
}
|
||||
};
|
||||
|
||||
struct my_error_with_vector
|
||||
{
|
||||
std::vector<int> value;
|
||||
};
|
||||
|
||||
leaf::result<void> fail()
|
||||
{
|
||||
return BOOST_LEAF_NEW_ERROR(
|
||||
@@ -87,6 +93,7 @@ leaf::result<void> fail()
|
||||
42,
|
||||
my_error<1>{1, "error one"},
|
||||
my_error<2>{2, "error two"},
|
||||
my_error_with_vector{{10, 20, 30}},
|
||||
leaf::e_errno{ENOENT},
|
||||
leaf::e_api_function{"my_api_function"} );
|
||||
}
|
||||
@@ -103,6 +110,7 @@ void leaf_throw()
|
||||
42,
|
||||
my_error<1>{1, "error one"},
|
||||
my_error<2>{2, "error two"},
|
||||
my_error_with_vector{{10, 20, 30}},
|
||||
leaf::e_errno{ENOENT},
|
||||
leaf::e_api_function{"my_api_function"} );
|
||||
}
|
||||
@@ -118,6 +126,7 @@ void throw_()
|
||||
42,
|
||||
my_error<1>{1, "error one"},
|
||||
my_error<2>{2, "error two"},
|
||||
my_error_with_vector{{10, 20, 30}},
|
||||
leaf::e_errno{ENOENT},
|
||||
leaf::e_api_function{"my_api_function"} );
|
||||
throw my_exception{};
|
||||
@@ -167,6 +176,13 @@ void check_diagnostic_details(boost::json::value const & j, bool has_source_loca
|
||||
BOOST_TEST_EQ(boost::json::value_to<int>(e2j.at("code")), 2);
|
||||
BOOST_TEST_EQ(boost::json::value_to<std::string>(e2j.at("message")), "error two");
|
||||
|
||||
auto const & vj = j.at("my_error_with_vector");
|
||||
BOOST_TEST(vj.is_array());
|
||||
BOOST_TEST_EQ(vj.as_array().size(), 3);
|
||||
BOOST_TEST_EQ(boost::json::value_to<int>(vj.as_array()[0]), 10);
|
||||
BOOST_TEST_EQ(boost::json::value_to<int>(vj.as_array()[1]), 20);
|
||||
BOOST_TEST_EQ(boost::json::value_to<int>(vj.as_array()[2]), 30);
|
||||
|
||||
auto const & ej = j.at("boost::leaf::e_errno");
|
||||
BOOST_TEST_EQ(boost::json::value_to<int>(ej.at("errno")), ENOENT);
|
||||
BOOST_TEST(!boost::json::value_to<std::string>(ej.at("strerror")).empty());
|
||||
|
||||
Reference in New Issue
Block a user