|
10 | 10 | #ifndef BOOST_JSON_IMPL_VISIT_HPP |
11 | 11 | #define BOOST_JSON_IMPL_VISIT_HPP |
12 | 12 |
|
| 13 | +#include <boost/type_traits/copy_cv_ref.hpp> |
| 14 | + |
13 | 15 | namespace boost { |
14 | 16 | namespace json { |
| 17 | +namespace detail { |
15 | 18 |
|
16 | | -template<class Visitor> |
| 19 | +template<class Visitor, class Value> |
17 | 20 | auto |
18 | 21 | visit( |
19 | 22 | Visitor&& v, |
20 | | - value& jv) -> decltype( |
21 | | - std::declval<Visitor>()(nullptr)) |
| 23 | + Value&& jv) -> decltype( |
| 24 | + static_cast<Visitor&&>(v)( |
| 25 | + std::declval< copy_cv_ref_t<std::nullptr_t, Value&&> >() ) ) |
22 | 26 | { |
| 27 | + auto&& vis_ref = static_cast<Visitor&&>(v); |
| 28 | + auto&& arg_ref = static_cast<Value&&>(jv); |
23 | 29 | switch(jv.kind()) |
24 | 30 | { |
25 | 31 | default: // unreachable()? |
26 | | - case kind::null: return std::forward<Visitor>(v)(nullptr); |
27 | | - case kind::bool_: return std::forward<Visitor>(v)(jv.get_bool()); |
28 | | - case kind::int64: return std::forward<Visitor>(v)(jv.get_int64()); |
29 | | - case kind::uint64: return std::forward<Visitor>(v)(jv.get_uint64()); |
30 | | - case kind::double_: return std::forward<Visitor>(v)(jv.get_double()); |
31 | | - case kind::string: return std::forward<Visitor>(v)(jv.get_string()); |
32 | | - case kind::array: return std::forward<Visitor>(v)(jv.get_array()); |
33 | | - case kind::object: return std::forward<Visitor>(v)(jv.get_object()); |
| 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() ); |
| 39 | + 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) ); |
| 43 | + } |
34 | 44 | } |
35 | 45 | } |
36 | 46 |
|
| 47 | +} // namespace detail |
| 48 | + |
| 49 | +template<class Visitor> |
| 50 | +auto |
| 51 | +visit( |
| 52 | + Visitor&& v, |
| 53 | + value& jv) -> decltype( |
| 54 | + static_cast<Visitor&&>(v)( std::declval<std::nullptr_t&>() ) ) |
| 55 | +{ |
| 56 | + return detail::visit( static_cast<Visitor&&>(v), jv ); |
| 57 | +} |
| 58 | + |
37 | 59 | template<class Visitor> |
38 | 60 | auto |
39 | 61 | visit( |
40 | 62 | Visitor&& v, |
41 | 63 | value const& jv) -> decltype( |
42 | | - std::declval<Visitor>()(nullptr)) |
| 64 | + static_cast<Visitor&&>(v)( std::declval<std::nullptr_t const&>() ) ) |
43 | 65 | { |
44 | | - switch (jv.kind()) |
45 | | - { |
46 | | - default: // unreachable()? |
47 | | - case kind::null: return std::forward<Visitor>(v)(nullptr); |
48 | | - case kind::bool_: return std::forward<Visitor>(v)(jv.get_bool()); |
49 | | - case kind::int64: return std::forward<Visitor>(v)(jv.get_int64()); |
50 | | - case kind::uint64: return std::forward<Visitor>(v)(jv.get_uint64()); |
51 | | - case kind::double_: return std::forward<Visitor>(v)(jv.get_double()); |
52 | | - case kind::string: return std::forward<Visitor>(v)(jv.get_string()); |
53 | | - case kind::array: return std::forward<Visitor>(v)(jv.get_array()); |
54 | | - case kind::object: return std::forward<Visitor>(v)(jv.get_object()); |
55 | | - } |
| 66 | + return detail::visit( static_cast<Visitor&&>(v), jv ); |
56 | 67 | } |
57 | 68 |
|
58 | 69 | } // namespace json |
|
0 commit comments