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_TO_HPP
13 : #define BOOST_JSON_VALUE_TO_HPP
14 :
15 : #include <boost/core/detail/static_assert.hpp>
16 : #include <boost/json/detail/value_to.hpp>
17 :
18 : namespace boost {
19 : namespace json {
20 :
21 : /** Convert a @ref value to an object of type `T`.
22 :
23 : This function attempts to convert a @ref value
24 : to `T` using
25 :
26 : @li one of @ref value's accessors, or
27 : @li a library-provided generic conversion, or
28 : @li a user-provided overload of `tag_invoke`.
29 :
30 : Out of the box the function supports default constructible types satisfying
31 : {req_SequenceContainer}, arrays, arithmetic types, `bool`, `std::tuple`,
32 : `std::pair`, `std::optional`, `std::variant`, `std::nullptr_t`, and structs
33 : and enums described using Boost.Describe.
34 :
35 : Conversion of other types is done by calling an overload of `tag_invoke`
36 : found by argument-dependent lookup. Its signature should be similar to:
37 :
38 : @code
39 : template< class FullContext >
40 : T tag_invoke( value_to_tag<T>, const value&, const Context& , const FullContext& );
41 : @endcode
42 :
43 : or
44 :
45 : @code
46 : T tag_invoke( value_to_tag<T>, const value&, const Context& );
47 : @endcode
48 :
49 : or
50 :
51 : @code
52 : result<T> tag_invoke( value_to_tag<T>, const value& );
53 : @endcode
54 :
55 : The overloads are checked for existence in that order and the first that
56 : matches will be selected.
57 :
58 : The object returned by the function call is returned by @ref value_to as
59 : the result of the conversion.
60 :
61 : The `ctx` argument can be used either as a tag type to provide conversions
62 : for third-party types, or to pass extra data to the conversion function.
63 :
64 : Overload **(3)** is **deleted** and participates in overload resolution
65 : only when `U` is not @ref value. The overload exists to prevent unintented
66 : creation of temporary @ref value instances, e.g.
67 :
68 : @code
69 : auto flag = value_to<bool>(true);
70 : @endcode
71 :
72 : @par Constraints
73 : @code
74 : ! std::is_reference< T >::value
75 : @endcode
76 :
77 : @par Exception Safety
78 : Strong guarantee.
79 :
80 : @tparam T The type to convert to.
81 :
82 : @tparam Context The type of context passed to the conversion function.
83 :
84 : @returns `jv` converted to `result<T>`.
85 :
86 : @param jv The @ref value to convert.
87 :
88 : @param ctx Context passed to the conversion function.
89 :
90 : @see @ref value_to_tag, @ref value_from,
91 : <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1895r0.pdf">
92 : tag_invoke: A general pattern for supporting customisable functions</a>
93 :
94 : @{
95 : */
96 : template< class T, class Context >
97 : T
98 HIT 410 : value_to( value const& jv, Context const& ctx )
99 : {
100 : BOOST_CORE_STATIC_ASSERT( ! std::is_reference<T>::value );
101 : using bare_T = detail::remove_cvref<T>;
102 : using cat = detail::value_to_category<Context, bare_T>;
103 410 : return detail::value_to_impl( cat(), value_to_tag<bare_T>(), jv, ctx );
104 : }
105 :
106 : /// Overload
107 : template<class T>
108 : T
109 131 : value_to(const value& jv)
110 : {
111 192 : return value_to<T>( jv, detail::no_context() );
112 : }
113 :
114 : /// Overload
115 : template<class T, class U
116 : #ifndef BOOST_JSON_DOCS
117 : , class = typename std::enable_if<!std::is_same<U, value>::value>::type
118 : #endif
119 : >
120 : T
121 : value_to(U const& jv) = delete;
122 : /// @}
123 :
124 : /** Convert a @ref value to a @ref boost::system::result.
125 :
126 : This function attempts to convert a @ref value to `result<T>` using
127 :
128 : @li one of @ref value's accessors, or
129 : @li a library-provided generic conversion, or
130 : @li a user-provided overload of `tag_invoke`.
131 :
132 : Out of the box the function supports default constructible types satisfying
133 : {req_SequenceContainer}, arrays, arithmetic types, `bool`, `std::tuple`,
134 : `std::pair`, `std::optional`, `std::variant`, `std::nullptr_t`, and structs
135 : and enums described using Boost.Describe.
136 :
137 : Conversion of other types is done by calling an overload of `tag_invoke`
138 : found by argument-dependent lookup. Its signature should be similar to:
139 :
140 : @code
141 : template< class FullContext >
142 : result<T> tag_invoke( try_value_to_tag<T>, const value&, const Context& , const FullContext& );
143 : @endcode
144 :
145 : or
146 :
147 : @code
148 : result<T> tag_invoke( try_value_to_tag<T>, const value&, const Context& );
149 : @endcode
150 :
151 : or
152 :
153 : @code
154 : result<T> tag_invoke( try_value_to_tag<T>, const value& );
155 : @endcode
156 :
157 : The overloads are checked for existence in that order and the first that
158 : matches will be selected.
159 :
160 : If an error occurs during conversion, the result will store the error code
161 : associated with the error. If an exception is thrown, the function will
162 : attempt to retrieve the associated error code and return it, otherwise it
163 : will return `error::exception`, unless the exception type is
164 : @ref std::bad_alloc, which will be allowed to propagate.
165 :
166 : The `ctx` argument can be used either as a tag type to provide conversions
167 : for third-party types, or to pass extra data to the conversion function.
168 :
169 : @par Constraints
170 : @code
171 : ! std::is_reference< T >::value
172 : @endcode
173 :
174 : @par Exception Safety
175 : Strong guarantee.
176 :
177 : @tparam T The type to convert to.
178 : @tparam Context The type of context passed to the conversion function.
179 :
180 : @param jv The @ref value to convert.
181 : @param ctx Context passed to the conversion function.
182 :
183 : @returns `jv` converted to `result<T>`.
184 :
185 : @see @ref value_to_tag, @ref value_to, @ref value_from,
186 : [tag_invoke: A general pattern for supporting customisable functions](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1895r0.pdf).
187 :
188 : @{
189 : */
190 : template< class T, class Context >
191 : typename result_for<T, value>::type
192 3763 : try_value_to( value const& jv, Context const& ctx )
193 : {
194 : BOOST_CORE_STATIC_ASSERT( ! std::is_reference<T>::value );
195 : using bare_T = detail::remove_cvref<T>;
196 : using cat = detail::value_to_category<Context, bare_T>;
197 3573 : return detail::value_to_impl(
198 3757 : cat(), try_value_to_tag<bare_T>(), jv, ctx );
199 : }
200 :
201 : /// Overload
202 : template<class T>
203 : typename result_for<T, value>::type
204 130 : try_value_to(const value& jv)
205 : {
206 163 : return try_value_to<T>( jv, detail::no_context() );
207 : }
208 : /// @}
209 :
210 : /** Determine if a @ref value can be converted to `T`.
211 :
212 : If @ref value can be converted to `T` via a
213 : call to @ref value_to, the static data member `value`
214 : is defined as `true`. Otherwise, `value` is
215 : defined as `false`.
216 :
217 : @see @ref value_to
218 : */
219 : #ifdef BOOST_JSON_DOCS
220 : template<class T>
221 : using has_value_to = __see_below__;
222 : #else
223 : template<class T>
224 : using has_value_to = detail::can_convert<
225 : detail::remove_cvref<T>, detail::value_to_conversion>;
226 : #endif
227 :
228 : } // namespace json
229 : } // namespace boost
230 :
231 : #endif
|