2
0
mirror of https://github.com/boostorg/json.git synced 2026-01-19 04:12:14 +00:00

rvalue ref overload for visit

This commit is contained in:
Dmitry Arkhipov
2023-11-24 15:37:08 +03:00
parent b07a034870
commit e8d8409928
3 changed files with 121 additions and 34 deletions

View File

@@ -10,41 +10,9 @@
#ifndef BOOST_JSON_IMPL_VISIT_HPP
#define BOOST_JSON_IMPL_VISIT_HPP
#include <boost/type_traits/copy_cv_ref.hpp>
namespace boost {
namespace json {
namespace detail {
template<class Visitor, class Value>
auto
visit(
Visitor&& v,
Value&& jv) -> decltype(
static_cast<Visitor&&>(v)(
std::declval< copy_cv_ref_t<std::nullptr_t, Value&&> >() ) )
{
auto&& vis_ref = static_cast<Visitor&&>(v);
auto&& arg_ref = static_cast<Value&&>(jv);
switch(jv.kind())
{
default: // unreachable()?
case kind::bool_: return vis_ref( arg_ref.get_bool() );
case kind::int64: return vis_ref( arg_ref.get_int64() );
case kind::uint64: return vis_ref( arg_ref.get_uint64() );
case kind::double_: return vis_ref( arg_ref.get_double() );
case kind::string: return vis_ref( arg_ref.get_string() );
case kind::array: return vis_ref( arg_ref.get_array() );
case kind::object: return vis_ref( arg_ref.get_object() );
case kind::null: {
std::nullptr_t np;
using Ref = copy_cv_ref_t<std::nullptr_t, Value&&>;
return vis_ref( static_cast<Ref>(np) );
}
}
}
} // namespace detail
template<class Visitor>
auto
@@ -53,7 +21,21 @@ visit(
value& jv) -> decltype(
static_cast<Visitor&&>(v)( std::declval<std::nullptr_t&>() ) )
{
return detail::visit( static_cast<Visitor&&>(v), jv );
switch(jv.kind())
{
default: // unreachable()?
case kind::string: return static_cast<Visitor&&>(v)( jv.get_string() );
case kind::array: return static_cast<Visitor&&>(v)( jv.get_array() );
case kind::object: return static_cast<Visitor&&>(v)( jv.get_object() );
case kind::bool_: return static_cast<Visitor&&>(v)( jv.get_bool() );
case kind::int64: return static_cast<Visitor&&>(v)( jv.get_int64() );
case kind::uint64: return static_cast<Visitor&&>(v)( jv.get_uint64() );
case kind::double_: return static_cast<Visitor&&>(v)( jv.get_double() );
case kind::null: {
auto np = nullptr;
return static_cast<Visitor&&>(v)(np) ;
}
}
}
template<class Visitor>
@@ -63,7 +45,43 @@ visit(
value const& jv) -> decltype(
static_cast<Visitor&&>(v)( std::declval<std::nullptr_t const&>() ) )
{
return detail::visit( static_cast<Visitor&&>(v), jv );
switch(jv.kind())
{
default: // unreachable()?
case kind::string: return static_cast<Visitor&&>(v)( jv.get_string() );
case kind::array: return static_cast<Visitor&&>(v)( jv.get_array() );
case kind::object: return static_cast<Visitor&&>(v)( jv.get_object() );
case kind::bool_: return static_cast<Visitor&&>(v)( jv.get_bool() );
case kind::int64: return static_cast<Visitor&&>(v)( jv.get_int64() );
case kind::uint64: return static_cast<Visitor&&>(v)( jv.get_uint64() );
case kind::double_: return static_cast<Visitor&&>(v)( jv.get_double() );
case kind::null: {
auto const np = nullptr;
return static_cast<Visitor&&>(v)(np) ;
}
}
}
template<class Visitor>
auto
visit(
Visitor&& v,
value&& jv) -> decltype(
static_cast<Visitor&&>(v)( std::declval<std::nullptr_t&&>() ) )
{
switch(jv.kind())
{
default: // unreachable()?
case kind::string: return static_cast<Visitor&&>(v)( std::move( jv.get_string() ) );
case kind::array: return static_cast<Visitor&&>(v)( std::move( jv.get_array() ) );
case kind::object: return static_cast<Visitor&&>(v)( std::move( jv.get_object() ) );
case kind::bool_: return static_cast<Visitor&&>(v)( std::move( jv.get_bool() ) );
case kind::int64: return static_cast<Visitor&&>(v)( std::move( jv.get_int64() ) );
case kind::uint64: return static_cast<Visitor&&>(v)( std::move( jv.get_uint64() ) );
case kind::double_: return static_cast<Visitor&&>(v)( std::move( jv.get_double() ) );
case kind::null: return static_cast<Visitor&&>(v)( std::nullptr_t() ) ;
}
}
} // namespace json

View File

@@ -40,6 +40,13 @@ visit(
Visitor &&v,
value const &jv) -> decltype(
static_cast<Visitor&&>(v)( std::declval<std::nullptr_t const&>() ) );
template<class Visitor>
auto
visit(
Visitor &&v,
value&& jv) -> decltype(
static_cast<Visitor&&>(v)( std::declval<std::nullptr_t&&>() ) );
/** @} */
} // namespace json

View File

@@ -60,6 +60,50 @@ public:
BOOST_TEST(visit(f{k}, v));
}
template<class T>
void
check_rvalue(kind k, T t)
{
struct f
{
kind k;
bool operator()(std::nullptr_t&&) && { return k == kind::null; }
bool operator()(bool&&) && { return k == kind::bool_; }
bool operator()(std::int64_t&&) && { return k == kind::int64; }
bool operator()(std::uint64_t&&) && { return k == kind::uint64; }
bool operator()(double&&) && { return k == kind::double_; }
bool operator()(string&&) && { return k == kind::string; }
bool operator()(array&&) && { return k == kind::array; }
bool operator()(object&&) && { return k == kind::object; }
bool operator()(...) && { return false; }
};
value v(t);
f f_{k};
BOOST_TEST(visit( std::move(f_), std::move(v) ));
}
template<class T>
void
check_nonref(kind k, T t)
{
struct f
{
kind k;
bool operator()(std::nullptr_t) && { return k == kind::null; }
bool operator()(bool) && { return k == kind::bool_; }
bool operator()(std::int64_t) && { return k == kind::int64; }
bool operator()(std::uint64_t) && { return k == kind::uint64; }
bool operator()(double) && { return k == kind::double_; }
bool operator()(string) && { return k == kind::string; }
bool operator()(array) && { return k == kind::array; }
bool operator()(object) && { return k == kind::object; }
bool operator()(...) && { return false; }
};
value v(t);
f f_{k};
BOOST_TEST(visit( std::move(f_), std::move(v) ));
}
void
testVisit()
{
@@ -80,6 +124,24 @@ public:
check_mutable(kind::string, string_kind);
check_mutable(kind::array, array_kind);
check_mutable(kind::object, object_kind);
check_rvalue(kind::null, nullptr);
check_rvalue(kind::bool_, true);
check_rvalue(kind::int64, -1);
check_rvalue(kind::uint64, 1U);
check_rvalue(kind::double_, 3.14);
check_rvalue(kind::string, string_kind);
check_rvalue(kind::array, array_kind);
check_rvalue(kind::object, object_kind);
check_nonref(kind::null, nullptr);
check_nonref(kind::bool_, true);
check_nonref(kind::int64, -1);
check_nonref(kind::uint64, 1U);
check_nonref(kind::double_, 3.14);
check_nonref(kind::string, string_kind);
check_nonref(kind::array, array_kind);
check_nonref(kind::object, object_kind);
}
void run()