Skip to content

Commit e8d8409

Browse files
committed
rvalue ref overload for visit
1 parent b07a034 commit e8d8409

File tree

3 files changed

+114
-27
lines changed

3 files changed

+114
-27
lines changed

include/boost/json/impl/visit.hpp

Lines changed: 45 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,60 +10,78 @@
1010
#ifndef BOOST_JSON_IMPL_VISIT_HPP
1111
#define BOOST_JSON_IMPL_VISIT_HPP
1212

13-
#include <boost/type_traits/copy_cv_ref.hpp>
14-
1513
namespace boost {
1614
namespace json {
17-
namespace detail {
1815

19-
template<class Visitor, class Value>
16+
17+
template<class Visitor>
2018
auto
2119
visit(
2220
Visitor&& v,
23-
Value&& jv) -> decltype(
24-
static_cast<Visitor&&>(v)(
25-
std::declval< copy_cv_ref_t<std::nullptr_t, Value&&> >() ) )
21+
value& jv) -> decltype(
22+
static_cast<Visitor&&>(v)( std::declval<std::nullptr_t&>() ) )
2623
{
27-
auto&& vis_ref = static_cast<Visitor&&>(v);
28-
auto&& arg_ref = static_cast<Value&&>(jv);
2924
switch(jv.kind())
3025
{
3126
default: // unreachable()?
32-
case kind::bool_: return vis_ref( arg_ref.get_bool() );
33-
case kind::int64: return vis_ref( arg_ref.get_int64() );
34-
case kind::uint64: return vis_ref( arg_ref.get_uint64() );
35-
case kind::double_: return vis_ref( arg_ref.get_double() );
36-
case kind::string: return vis_ref( arg_ref.get_string() );
37-
case kind::array: return vis_ref( arg_ref.get_array() );
38-
case kind::object: return vis_ref( arg_ref.get_object() );
27+
case kind::string: return static_cast<Visitor&&>(v)( jv.get_string() );
28+
case kind::array: return static_cast<Visitor&&>(v)( jv.get_array() );
29+
case kind::object: return static_cast<Visitor&&>(v)( jv.get_object() );
30+
case kind::bool_: return static_cast<Visitor&&>(v)( jv.get_bool() );
31+
case kind::int64: return static_cast<Visitor&&>(v)( jv.get_int64() );
32+
case kind::uint64: return static_cast<Visitor&&>(v)( jv.get_uint64() );
33+
case kind::double_: return static_cast<Visitor&&>(v)( jv.get_double() );
3934
case kind::null: {
40-
std::nullptr_t np;
41-
using Ref = copy_cv_ref_t<std::nullptr_t, Value&&>;
42-
return vis_ref( static_cast<Ref>(np) );
35+
auto np = nullptr;
36+
return static_cast<Visitor&&>(v)(np) ;
4337
}
4438
}
4539
}
4640

47-
} // namespace detail
48-
4941
template<class Visitor>
5042
auto
5143
visit(
5244
Visitor&& v,
53-
value& jv) -> decltype(
54-
static_cast<Visitor&&>(v)( std::declval<std::nullptr_t&>() ) )
45+
value const& jv) -> decltype(
46+
static_cast<Visitor&&>(v)( std::declval<std::nullptr_t const&>() ) )
5547
{
56-
return detail::visit( static_cast<Visitor&&>(v), jv );
48+
switch(jv.kind())
49+
{
50+
default: // unreachable()?
51+
case kind::string: return static_cast<Visitor&&>(v)( jv.get_string() );
52+
case kind::array: return static_cast<Visitor&&>(v)( jv.get_array() );
53+
case kind::object: return static_cast<Visitor&&>(v)( jv.get_object() );
54+
case kind::bool_: return static_cast<Visitor&&>(v)( jv.get_bool() );
55+
case kind::int64: return static_cast<Visitor&&>(v)( jv.get_int64() );
56+
case kind::uint64: return static_cast<Visitor&&>(v)( jv.get_uint64() );
57+
case kind::double_: return static_cast<Visitor&&>(v)( jv.get_double() );
58+
case kind::null: {
59+
auto const np = nullptr;
60+
return static_cast<Visitor&&>(v)(np) ;
61+
}
62+
}
5763
}
5864

65+
5966
template<class Visitor>
6067
auto
6168
visit(
6269
Visitor&& v,
63-
value const& jv) -> decltype(
64-
static_cast<Visitor&&>(v)( std::declval<std::nullptr_t const&>() ) )
70+
value&& jv) -> decltype(
71+
static_cast<Visitor&&>(v)( std::declval<std::nullptr_t&&>() ) )
6572
{
66-
return detail::visit( static_cast<Visitor&&>(v), jv );
73+
switch(jv.kind())
74+
{
75+
default: // unreachable()?
76+
case kind::string: return static_cast<Visitor&&>(v)( std::move( jv.get_string() ) );
77+
case kind::array: return static_cast<Visitor&&>(v)( std::move( jv.get_array() ) );
78+
case kind::object: return static_cast<Visitor&&>(v)( std::move( jv.get_object() ) );
79+
case kind::bool_: return static_cast<Visitor&&>(v)( std::move( jv.get_bool() ) );
80+
case kind::int64: return static_cast<Visitor&&>(v)( std::move( jv.get_int64() ) );
81+
case kind::uint64: return static_cast<Visitor&&>(v)( std::move( jv.get_uint64() ) );
82+
case kind::double_: return static_cast<Visitor&&>(v)( std::move( jv.get_double() ) );
83+
case kind::null: return static_cast<Visitor&&>(v)( std::nullptr_t() ) ;
84+
}
6785
}
6886

6987
} // namespace json

include/boost/json/visit.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@ visit(
4040
Visitor &&v,
4141
value const &jv) -> decltype(
4242
static_cast<Visitor&&>(v)( std::declval<std::nullptr_t const&>() ) );
43+
44+
template<class Visitor>
45+
auto
46+
visit(
47+
Visitor &&v,
48+
value&& jv) -> decltype(
49+
static_cast<Visitor&&>(v)( std::declval<std::nullptr_t&&>() ) );
4350
/** @} */
4451

4552
} // namespace json

test/visit.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,50 @@ class visit_test
6060
BOOST_TEST(visit(f{k}, v));
6161
}
6262

63+
template<class T>
64+
void
65+
check_rvalue(kind k, T t)
66+
{
67+
struct f
68+
{
69+
kind k;
70+
bool operator()(std::nullptr_t&&) && { return k == kind::null; }
71+
bool operator()(bool&&) && { return k == kind::bool_; }
72+
bool operator()(std::int64_t&&) && { return k == kind::int64; }
73+
bool operator()(std::uint64_t&&) && { return k == kind::uint64; }
74+
bool operator()(double&&) && { return k == kind::double_; }
75+
bool operator()(string&&) && { return k == kind::string; }
76+
bool operator()(array&&) && { return k == kind::array; }
77+
bool operator()(object&&) && { return k == kind::object; }
78+
bool operator()(...) && { return false; }
79+
};
80+
value v(t);
81+
f f_{k};
82+
BOOST_TEST(visit( std::move(f_), std::move(v) ));
83+
}
84+
85+
template<class T>
86+
void
87+
check_nonref(kind k, T t)
88+
{
89+
struct f
90+
{
91+
kind k;
92+
bool operator()(std::nullptr_t) && { return k == kind::null; }
93+
bool operator()(bool) && { return k == kind::bool_; }
94+
bool operator()(std::int64_t) && { return k == kind::int64; }
95+
bool operator()(std::uint64_t) && { return k == kind::uint64; }
96+
bool operator()(double) && { return k == kind::double_; }
97+
bool operator()(string) && { return k == kind::string; }
98+
bool operator()(array) && { return k == kind::array; }
99+
bool operator()(object) && { return k == kind::object; }
100+
bool operator()(...) && { return false; }
101+
};
102+
value v(t);
103+
f f_{k};
104+
BOOST_TEST(visit( std::move(f_), std::move(v) ));
105+
}
106+
63107
void
64108
testVisit()
65109
{
@@ -80,6 +124,24 @@ class visit_test
80124
check_mutable(kind::string, string_kind);
81125
check_mutable(kind::array, array_kind);
82126
check_mutable(kind::object, object_kind);
127+
128+
check_rvalue(kind::null, nullptr);
129+
check_rvalue(kind::bool_, true);
130+
check_rvalue(kind::int64, -1);
131+
check_rvalue(kind::uint64, 1U);
132+
check_rvalue(kind::double_, 3.14);
133+
check_rvalue(kind::string, string_kind);
134+
check_rvalue(kind::array, array_kind);
135+
check_rvalue(kind::object, object_kind);
136+
137+
check_nonref(kind::null, nullptr);
138+
check_nonref(kind::bool_, true);
139+
check_nonref(kind::int64, -1);
140+
check_nonref(kind::uint64, 1U);
141+
check_nonref(kind::double_, 3.14);
142+
check_nonref(kind::string, string_kind);
143+
check_nonref(kind::array, array_kind);
144+
check_nonref(kind::object, object_kind);
83145
}
84146

85147
void run()

0 commit comments

Comments
 (0)