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