TLA Line data Source code
1 : //
2 : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 : // Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
4 : // Copyright (c) 2022 Dmitry Arkhipov (grisumbras@gmail.com)
5 : //
6 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
7 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 : //
9 : // Official repository: https://github.com/boostorg/json
10 : //
11 :
12 : #ifndef BOOST_JSON_VALUE_FROM_HPP
13 : #define BOOST_JSON_VALUE_FROM_HPP
14 :
15 : #include <boost/core/detail/static_assert.hpp>
16 : #include <boost/json/detail/value_from.hpp>
17 :
18 : namespace boost {
19 : namespace json {
20 :
21 : /** Convert an object of type `T` to @ref value.
22 :
23 : This function attempts to convert an object of type `T` to @ref value using
24 :
25 : - one of @ref value's constructors,
26 : - a library-provided generic conversion, or
27 : - a user-provided overload of `tag_invoke`.
28 :
29 : In order to perform the conversion the function selects an appropriate
30 : implementation based on the types `T` and `Context` (if provided).
31 :
32 : 1. If `Context` is available and is not `std::tuple<C...>`
33 :
34 : a. check if `use_category<T, Context>::value` is not
35 : @ref conversion_category::unknown; otherwise
36 :
37 : b. check if a `tag_invoke` overload from the list below that takes a
38 : `Context const&` exists.
39 :
40 : 2. Otherwise, if `Context` is available, and is `std::tuple<C...>` repeat
41 : steps **1** and **2** recursively for every `C` until either
42 : step **1.a** or **1.b** succeeds for some `C`.
43 :
44 : 3. Failing that,
45 :
46 : a. check if `use_category<T>::value` is not
47 : @ref conversion_category::unknown; otherwise
48 :
49 : b. check if a `tag_invoke` overload from the list below that takes only
50 : 2 parameters exists; otherwise
51 :
52 : c. check if `T` is one of @ref value, @ref array, @ref object,
53 : or @ref string; otherwise
54 :
55 : d. check if `T` matches one of the categories of types described in the
56 : table "Conversion categories" in \<\<Value Conversion>> section.
57 :
58 : These steps determine both the appropriate category of conversion for `T`,
59 : and, if necessary, the effective context `C` that will be used for
60 : conversion. If the category is selected on steps **1.a**, **3.a**, **3.c**,
61 : or **3.d**, the library provides a suitable conversion implementation.
62 : If the category is selected on steps **2.b** or **3.b**, then a
63 : user-provided `tag_invoke` overload is used.
64 :
65 : The overloads of `tag_invoke` that will be considered by this function
66 : are in the following list. Overloads that appear higher in the list have
67 : higher priority.
68 :
69 : @code
70 : template< class FullContext >
71 : void tag_invoke( value_from_tag, value&, T, const Context&, const FullContext& );
72 :
73 : void tag_invoke( value_from_tag, value&, T, const Context& );
74 :
75 : void tag_invoke( value_from_tag, value&, T );
76 : @endcode
77 :
78 : The `ctx` argument can be used either as a tag type to provide conversions
79 : for third-party types, or to pass extra data to the conversion function.
80 :
81 : Overloads **(2)** and **(4)** construct their return value using the
82 : @ref storage_ptr `sp`, which ensures that the memory resource is correctly
83 : propagated.
84 :
85 : @par Exception Safety
86 : Strong guarantee.
87 :
88 : @tparam T The type of the object to convert.
89 :
90 : @tparam Context The type of context passed to the conversion function.
91 :
92 : @param t The object to convert.
93 :
94 : @param ctx Context passed to the conversion function.
95 :
96 : @param jv @ref value out parameter.
97 :
98 : @see @ref value_from_tag, @ref value_to,
99 : <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1895r0.pdf">
100 : tag_invoke: A general pattern for supporting customisable functions</a>
101 : */
102 : /// @{
103 : template< class T, class Context >
104 : void
105 HIT 7056 : value_from(
106 : T&& t,
107 : Context const& ctx,
108 : value& jv)
109 : {
110 : using bare_T = detail::remove_cvref<T>;
111 : using cat = detail::value_from_category<Context, bare_T>;
112 7056 : detail::value_from_impl( cat(), jv, std::forward<T>(t), ctx );
113 7056 : }
114 :
115 : /** Overload
116 : @param t
117 : @param ctx
118 : @param sp A storage pointer referring to the memory resource to use for the
119 : returned @ref value.
120 :
121 : @return Overloads **(2)** and **(4)** return `t` converted to @ref value.
122 : Overloads **(1)** and **3** return `void` instead and pass their result via
123 : the out parameter `jv`.
124 : */
125 : template< class T, class Context >
126 : #ifndef BOOST_JSON_DOCS
127 : typename std::enable_if<
128 : !std::is_same< detail::remove_cvref<Context>, storage_ptr >::value &&
129 : !std::is_same< detail::remove_cvref<Context>, value >::value,
130 : value >::type
131 : #else
132 : value
133 : #endif
134 7037 : value_from(
135 : T&& t,
136 : Context const& ctx,
137 : storage_ptr sp = {})
138 : {
139 7037 : value jv(std::move(sp));
140 7037 : value_from( static_cast<T&&>(t), ctx, jv );
141 7037 : return jv;
142 MIS 0 : }
143 :
144 : /// Overload
145 : template<class T>
146 : void
147 HIT 19 : value_from(
148 : T&& t,
149 : value& jv)
150 : {
151 19 : value_from( static_cast<T&&>(t), detail::no_context(), jv );
152 19 : }
153 :
154 : /// Overload
155 : template<class T>
156 : value
157 297 : value_from(
158 : T&& t,
159 : storage_ptr sp = {})
160 : {
161 : return value_from(
162 297 : static_cast<T&&>(t), detail::no_context(), std::move(sp) );
163 : }
164 : /// @}
165 :
166 : /** Determine if `T` can be converted to @ref value.
167 :
168 : If `T` can be converted to @ref value via a call to @ref value_from, the
169 : static data member `value` is defined as `true`. Otherwise, `value` is
170 : defined as `false`.
171 :
172 : @see @ref value_from.
173 : */
174 : #ifdef BOOST_JSON_DOCS
175 : template<class T>
176 : using has_value_from = __see_below__;
177 : #else
178 : template<class T>
179 : using has_value_from = detail::can_convert<
180 : detail::remove_cvref<T>, detail::value_from_conversion>;
181 : #endif
182 :
183 : } // namespace json
184 : } // namespace boost
185 :
186 : #endif
|