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 404 : 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 : BOOST_CORE_STATIC_ASSERT((
103 : detail::conversion_round_trips<
104 : Context, bare_T, detail::value_to_conversion>::value));
105 : using cat = detail::value_to_category<Context, bare_T>;
106 404 : return detail::value_to_impl( cat(), value_to_tag<bare_T>(), jv, ctx );
107 : }
108 :
109 : /// Overload
110 : template<class T>
111 : T
112 125 : value_to(const value& jv)
113 : {
114 186 : return value_to<T>( jv, detail::no_context() );
115 : }
116 :
117 : /// Overload
118 : template<class T, class U
119 : #ifndef BOOST_JSON_DOCS
120 : , class = typename std::enable_if<!std::is_same<U, value>::value>::type
121 : #endif
122 : >
123 : T
124 : value_to(U const& jv) = delete;
125 : /// @}
126 :
127 : /** Convert a @ref value to a @ref boost::system::result.
128 :
129 : This function attempts to convert a @ref value to `result<T>` using
130 :
131 : @li one of @ref value's accessors, or
132 : @li a library-provided generic conversion, or
133 : @li a user-provided overload of `tag_invoke`.
134 :
135 : Out of the box the function supports default constructible types satisfying
136 : {req_SequenceContainer}, arrays, arithmetic types, `bool`, `std::tuple`,
137 : `std::pair`, `std::optional`, `std::variant`, `std::nullptr_t`, and structs
138 : and enums described using Boost.Describe.
139 :
140 : Conversion of other types is done by calling an overload of `tag_invoke`
141 : found by argument-dependent lookup. Its signature should be similar to:
142 :
143 : @code
144 : template< class FullContext >
145 : result<T> tag_invoke( try_value_to_tag<T>, const value&, const Context& , const FullContext& );
146 : @endcode
147 :
148 : or
149 :
150 : @code
151 : result<T> tag_invoke( try_value_to_tag<T>, const value&, const Context& );
152 : @endcode
153 :
154 : or
155 :
156 : @code
157 : result<T> tag_invoke( try_value_to_tag<T>, const value& );
158 : @endcode
159 :
160 : The overloads are checked for existence in that order and the first that
161 : matches will be selected.
162 :
163 : If an error occurs during conversion, the result will store the error code
164 : associated with the error. If an exception is thrown, the function will
165 : attempt to retrieve the associated error code and return it, otherwise it
166 : will return `error::exception`, unless the exception type is
167 : @ref std::bad_alloc, which will be allowed to propagate.
168 :
169 : The `ctx` argument can be used either as a tag type to provide conversions
170 : for third-party types, or to pass extra data to the conversion function.
171 :
172 : @par Constraints
173 : @code
174 : ! std::is_reference< T >::value
175 : @endcode
176 :
177 : @par Exception Safety
178 : Strong guarantee.
179 :
180 : @tparam T The type to convert to.
181 : @tparam Context The type of context passed to the conversion function.
182 :
183 : @param jv The @ref value to convert.
184 : @param ctx Context passed to the conversion function.
185 :
186 : @returns `jv` converted to `result<T>`.
187 :
188 : @see @ref value_to_tag, @ref value_to, @ref value_from,
189 : [tag_invoke: A general pattern for supporting customisable functions](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1895r0.pdf).
190 :
191 : @{
192 : */
193 : template< class T, class Context >
194 : typename result_for<T, value>::type
195 3745 : try_value_to( value const& jv, Context const& ctx )
196 : {
197 : BOOST_CORE_STATIC_ASSERT( ! std::is_reference<T>::value );
198 : using bare_T = detail::remove_cvref<T>;
199 : BOOST_CORE_STATIC_ASSERT((
200 : detail::conversion_round_trips<
201 : Context, bare_T, detail::value_to_conversion>::value));
202 : using cat = detail::value_to_category<Context, bare_T>;
203 3555 : return detail::value_to_impl(
204 3739 : cat(), try_value_to_tag<bare_T>(), jv, ctx );
205 : }
206 :
207 : /// Overload
208 : template<class T>
209 : typename result_for<T, value>::type
210 130 : try_value_to(const value& jv)
211 : {
212 163 : return try_value_to<T>( jv, detail::no_context() );
213 : }
214 : /// @}
215 :
216 : /** Determine if a @ref value can be converted to `T`.
217 :
218 : If @ref value can be converted to `T` via a
219 : call to @ref value_to, the static data member `value`
220 : is defined as `true`. Otherwise, `value` is
221 : defined as `false`.
222 :
223 : @see @ref value_to
224 : */
225 : #ifdef BOOST_JSON_DOCS
226 : template<class T>
227 : using has_value_to = __see_below__;
228 : #else
229 : template<class T>
230 : using has_value_to = detail::can_convert<
231 : detail::remove_cvref<T>, detail::value_to_conversion>;
232 : #endif
233 :
234 : } // namespace json
235 : } // namespace boost
236 :
237 : #endif
|