1  
//
1  
//
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3  
// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
3  
// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
4  
// Copyright (c) 2022 Dmitry Arkhipov (grisumbras@gmail.com)
4  
// Copyright (c) 2022 Dmitry Arkhipov (grisumbras@gmail.com)
5  
//
5  
//
6  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
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)
7  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8  
//
8  
//
9  
// Official repository: https://github.com/boostorg/json
9  
// Official repository: https://github.com/boostorg/json
10  
//
10  
//
11  

11  

12  
#ifndef BOOST_JSON_VALUE_FROM_HPP
12  
#ifndef BOOST_JSON_VALUE_FROM_HPP
13  
#define BOOST_JSON_VALUE_FROM_HPP
13  
#define BOOST_JSON_VALUE_FROM_HPP
14 -
#include <boost/core/detail/static_assert.hpp>
 
15  

14  

16  
#include <boost/json/detail/value_from.hpp>
15  
#include <boost/json/detail/value_from.hpp>
17  

16  

18  
namespace boost {
17  
namespace boost {
19  
namespace json {
18  
namespace json {
20  

19  

21  
/** Convert an object of type `T` to @ref value.
20  
/** Convert an object of type `T` to @ref value.
22  

21  

23  
    This function attempts to convert an object
22  
    This function attempts to convert an object
24  
    of type `T` to @ref value using
23  
    of type `T` to @ref value using
25  

24  

26  
    @li one of @ref value's constructors,
25  
    @li one of @ref value's constructors,
27  

26  

28  
    @li a library-provided generic conversion, or
27  
    @li a library-provided generic conversion, or
29  

28  

30  
    @li a user-provided overload of `tag_invoke`.
29  
    @li a user-provided overload of `tag_invoke`.
31  

30  

32 -
    Out of the function supports default constructible types satisfying
31 +
    Out of the box the function supports types satisfying
33 -
    {req_SequenceContainer}, arrays, arithmetic types, `bool`, `std::tuple`,
32 +
    <a href="https://en.cppreference.com/w/cpp/named_req/SequenceContainer"><em>SequenceContainer</em></a>,
34 -
    `std::pair`, `std::optional`, `std::variant`, `std::nullptr_t`, and structs
33 +
    arrays, arithmetic types, `bool`, `std::tuple`, `std::pair`,
35 -
    and enums described using Boost.Describe.
34 +
    `std::variant`, `std::optional`, `std::monostate`, and `std::nullopt_t`.
36  

35  

37  
    Conversion of other types is done by calling an overload of `tag_invoke`
36  
    Conversion of other types is done by calling an overload of `tag_invoke`
38  
    found by argument-dependent lookup. Its signature should be similar to:
37  
    found by argument-dependent lookup. Its signature should be similar to:
39  

38  

40  
    @code
39  
    @code
41  
    template< class FullContext >
40  
    template< class FullContext >
42 -
    void tag_invoke( value_from_tag, value&, T, const Context&, const FullContext& );
41 +
    void tag_invoke( value_from_tag, value&, T,  const Context& , const FullContext& );
43  
    @endcode
42  
    @endcode
44  

43  

45  
    or
44  
    or
46  

45  

47  
    @code
46  
    @code
48 -
    void tag_invoke( value_from_tag, value&, T, const Context& );
47 +
    void tag_invoke( value_from_tag, value&, T,  const Context& );
49  
    @endcode
48  
    @endcode
50  

49  

51  
    or
50  
    or
52  

51  

53  
    @code
52  
    @code
54  
    void tag_invoke( value_from_tag, value&, T );
53  
    void tag_invoke( value_from_tag, value&, T );
55  
    @endcode
54  
    @endcode
56  

55  

57  
    The overloads are checked for existence in that order and the first that
56  
    The overloads are checked for existence in that order and the first that
58  
    matches will be selected. <br>
57  
    matches will be selected. <br>
59  

58  

60  
    The `ctx` argument can be used either as a tag type to provide conversions
59  
    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.
60  
    for third-party types, or to pass extra data to the conversion function.
62 -
    Overloads **(2)** and **(4)** construct their return value using the
 
63 -
    @ref storage_ptr `sp`, which ensures that the memory resource is correctly
 
64 -
    propagated.
 
65 -

 
66  

61  

67  
    @par Exception Safety
62  
    @par Exception Safety
68  
    Strong guarantee.
63  
    Strong guarantee.
69  

64  

70  
    @tparam T The type of the object to convert.
65  
    @tparam T The type of the object to convert.
71  

66  

72  
    @tparam Context The type of context passed to the conversion function.
67  
    @tparam Context The type of context passed to the conversion function.
73  

68  

74  
    @param t The object to convert.
69  
    @param t The object to convert.
75  

70  

76  
    @param ctx Context passed to the conversion function.
71  
    @param ctx Context passed to the conversion function.
77  

72  

78  
    @param jv @ref value out parameter.
73  
    @param jv @ref value out parameter.
79  

74  

80  
    @see @ref value_from_tag, @ref value_to,
75  
    @see @ref value_from_tag, @ref value_to,
81  
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1895r0.pdf">
76  
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1895r0.pdf">
82  
        tag_invoke: A general pattern for supporting customisable functions</a>
77  
        tag_invoke: A general pattern for supporting customisable functions</a>
83 -
/// @{
 
84  
*/
78  
*/
85  
template< class T, class Context >
79  
template< class T, class Context >
86  
void
80  
void
87  
value_from(
81  
value_from(
88  
    T&& t,
82  
    T&& t,
89  
    Context const& ctx,
83  
    Context const& ctx,
90  
    value& jv)
84  
    value& jv)
91  
{
85  
{
92 -
    using bare_T = detail::remove_cvref<T>;
86 +
    using Attrs = detail::value_from_attrs<Context, T>;
93 -
    BOOST_CORE_STATIC_ASSERT((
87 +
    BOOST_STATIC_ASSERT(detail::conversion_round_trips<
94 -
        detail::conversion_round_trips<
88 +
        Context,
95 -
            Context, bare_T, detail::value_from_conversion>::value));
89 +
        typename Attrs::representation,
96 -
    using cat = detail::value_from_category<Context, bare_T>;
90 +
        detail::value_from_conversion>::value);
97 -
    detail::value_from_impl( cat(), jv, std::forward<T>(t), ctx );
91 +

 
92 +
    detail::value_from_impl(
 
93 +
        typename Attrs::category(),
 
94 +
        jv,
 
95 +
        detail::to_representation<Context>( static_cast<T&&>(t) ),
 
96 +
        ctx );
98  
}
97  
}
99  

98  

100 -
/** Overload
99 +
/** Convert an object of type `T` to @ref value.
101 -
   @param t
 
102 -
   @param ctx
 
103 -
   @param sp A storage pointer referring to the memory resource to use for the
 
104 -
   returned @ref value.
 
105  

100  

106 -
   @return Overloads **(2)** and **(4)** return `t` converted to @ref value.
101 +
    This function attempts to convert an object
107 -
   Overloads **(1)** and **3** return `void` instead and pass their result via
102 +
    of type `T` to @ref value using
108 -
   the out parameter `jv`.
103 +

 
104 +
    @li one of @ref value's constructors,
 
105 +

 
106 +
    @li a library-provided generic conversion, or
 
107 +

 
108 +
    @li a user-provided overload of `tag_invoke`.
 
109 +

 
110 +
    Out of the box the function supports types satisfying
 
111 +
    <a href="https://en.cppreference.com/w/cpp/named_req/SequenceContainer"><em>SequenceContainer</em></a>,
 
112 +
    arrays, arithmetic types, `bool`, `std::tuple`, `std::pair`,
 
113 +
    `std::variant`, `std::optional`, `std::monostate`, and `std::nullopt_t`.
 
114 +

 
115 +
    Conversion of other types is done by calling an overload of `tag_invoke`
 
116 +
    found by argument-dependent lookup. Its signature should be similar to:
 
117 +

 
118 +
    @code
 
119 +
    template< class FullContext >
 
120 +
    void tag_invoke( value_from_tag, value&, T,  const Context& , const FullContext& );
 
121 +
    @endcode
 
122 +

 
123 +
    or
 
124 +

 
125 +
    @code
 
126 +
    void tag_invoke( value_from_tag, value&, T,  const Context& );
 
127 +
    @endcode
 
128 +

 
129 +
    or
 
130 +

 
131 +
    @code
 
132 +
    void tag_invoke( value_from_tag, value&, T );
 
133 +
    @endcode
 
134 +

 
135 +
    The overloads are checked for existence in that order and the first that
 
136 +
    matches will be selected. <br>
 
137 +

 
138 +
    A @ref value constructed with the @ref storage_ptr passed to
 
139 +
    @ref value_from is passed as the second argument to ensure that the memory
 
140 +
    resource is correctly propagated.
 
141 +

 
142 +
    @par Exception Safety
 
143 +
    Strong guarantee.
 
144 +

 
145 +
    @tparam T The type of the object to convert.
 
146 +

 
147 +
    @tparam Context The type of context passed to the conversion function.
 
148 +

 
149 +
    @returns `t` converted to @ref value.
 
150 +

 
151 +
    @param t The object to convert.
 
152 +

 
153 +
    @param ctx Context passed to the conversion function.
 
154 +

 
155 +
    @param sp A storage pointer referring to the memory resource
 
156 +
    to use for the returned @ref value. The default argument for this
 
157 +
    parameter is `{}`.
 
158 +

 
159 +
    @see @ref value_from_tag, @ref value_to,
 
160 +
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1895r0.pdf">
 
161 +
        tag_invoke: A general pattern for supporting customisable functions</a>
109  
*/
162  
*/
110  
template< class T, class Context >
163  
template< class T, class Context >
111  
#ifndef BOOST_JSON_DOCS
164  
#ifndef BOOST_JSON_DOCS
112  
typename std::enable_if<
165  
typename std::enable_if<
113  
    !std::is_same< detail::remove_cvref<Context>, storage_ptr >::value &&
166  
    !std::is_same< detail::remove_cvref<Context>, storage_ptr >::value &&
114  
    !std::is_same< detail::remove_cvref<Context>, value >::value,
167  
    !std::is_same< detail::remove_cvref<Context>, value >::value,
115  
    value >::type
168  
    value >::type
116  
#else
169  
#else
117  
value
170  
value
118  
#endif
171  
#endif
119  
value_from(
172  
value_from(
120  
    T&& t,
173  
    T&& t,
121  
    Context const& ctx,
174  
    Context const& ctx,
122  
    storage_ptr sp = {})
175  
    storage_ptr sp = {})
123  
{
176  
{
124  
    value jv(std::move(sp));
177  
    value jv(std::move(sp));
125  
    value_from( static_cast<T&&>(t), ctx, jv );
178  
    value_from( static_cast<T&&>(t), ctx, jv );
126  
    return jv;
179  
    return jv;
127  
}
180  
}
128  

181  

129 -
/// Overload
182 +
/** Convert an object of type `T` to @ref value.
 
183 +

 
184 +
    This function attempts to convert an object
 
185 +
    of type `T` to @ref value using
 
186 +

 
187 +
    @li one of @ref value's constructors,
 
188 +

 
189 +
    @li a library-provided generic conversion, or
 
190 +

 
191 +
    @li a user-provided overload of `tag_invoke`.
 
192 +

 
193 +
    Out of the box the function supports types satisfying
 
194 +
    <a href="https://en.cppreference.com/w/cpp/named_req/SequenceContainer"><em>SequenceContainer</em></a>,
 
195 +
    arrays, arithmetic types, `bool`, `std::tuple`, `std::pair`,
 
196 +
    `std::variant`, `std::optional`, `std::monostate`, and `std::nullopt_t`.
 
197 +

 
198 +
    Conversion of other types is done by calling an overload of `tag_invoke`
 
199 +
    found by argument-dependent lookup. Its signature should be similar to:
 
200 +

 
201 +
    @code
 
202 +
    void tag_invoke( value_from_tag, value&, T );
 
203 +
    @endcode
 
204 +

 
205 +
    @par Exception Safety
 
206 +
    Strong guarantee.
 
207 +

 
208 +
    @tparam T The type of the object to convert.
 
209 +

 
210 +
    @param t The object to convert.
 
211 +

 
212 +
    @param jv @ref value out parameter.
 
213 +

 
214 +
    @see @ref value_from_tag, @ref value_to,
 
215 +
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1895r0.pdf">
 
216 +
        tag_invoke: A general pattern for supporting customisable functions</a>
 
217 +
*/
130  
template<class T>
218  
template<class T>
131  
void
219  
void
132  
value_from(
220  
value_from(
133  
    T&& t,
221  
    T&& t,
134  
    value& jv)
222  
    value& jv)
135  
{
223  
{
136  
   value_from( static_cast<T&&>(t), detail::no_context(), jv );
224  
   value_from( static_cast<T&&>(t), detail::no_context(), jv );
137  
}
225  
}
138  

226  

139 -
/// Overload
227 +
/** Convert an object of type `T` to @ref value.
 
228 +

 
229 +
    This function attempts to convert an object
 
230 +
    of type `T` to @ref value using
 
231 +

 
232 +
    @li one of @ref value's constructors,
 
233 +

 
234 +
    @li a library-provided generic conversion, or
 
235 +

 
236 +
    @li a user-provided overload of `tag_invoke`.
 
237 +

 
238 +
    Out of the box the function supports types satisfying
 
239 +
    <a href="https://en.cppreference.com/w/cpp/named_req/SequenceContainer"><em>SequenceContainer</em></a>,
 
240 +
    arrays, arithmetic types, `bool`, `std::tuple`, `std::pair`,
 
241 +
    `std::variant`, `std::optional`, `std::monostate`, and `std::nullopt_t`.
 
242 +

 
243 +
    Conversion of other types is done by calling an overload of `tag_invoke`
 
244 +
    found by argument-dependent lookup. Its signature should be similar to:
 
245 +

 
246 +
    @code
 
247 +
    void tag_invoke( value_from_tag, value&, T );
 
248 +
    @endcode
 
249 +

 
250 +
    A @ref value constructed
 
251 +
    with the @ref storage_ptr passed to @ref value_from is
 
252 +
    passed as the second argument to ensure that the memory
 
253 +
    resource is correctly propagated.
 
254 +

 
255 +
    @par Exception Safety
 
256 +
    Strong guarantee.
 
257 +

 
258 +
    @tparam T The type of the object to convert.
 
259 +

 
260 +
    @returns `t` converted to @ref value.
 
261 +

 
262 +
    @param t The object to convert.
 
263 +

 
264 +
    @param sp A storage pointer referring to the memory resource
 
265 +
    to use for the returned @ref value. The default argument for this
 
266 +
    parameter is `{}`.
 
267 +

 
268 +
    @see @ref value_from_tag, @ref value_to,
 
269 +
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1895r0.pdf">
 
270 +
        tag_invoke: A general pattern for supporting customisable functions</a>
 
271 +
*/
140  
template<class T>
272  
template<class T>
141  
value
273  
value
142  
value_from(
274  
value_from(
143  
    T&& t,
275  
    T&& t,
144  
    storage_ptr sp = {})
276  
    storage_ptr sp = {})
145  
{
277  
{
146  
   return value_from(
278  
   return value_from(
147  
           static_cast<T&&>(t), detail::no_context(), std::move(sp) );
279  
           static_cast<T&&>(t), detail::no_context(), std::move(sp) );
148 -
/// @}
 
149  
}
280  
}
150  

281  

151  
/** Determine if `T` can be converted to @ref value.
282  
/** Determine if `T` can be converted to @ref value.
152  

283  

153 -
    If `T` can be converted to @ref value via a call to @ref value_from, the
284 +
    If `T` can be converted to @ref value via a
154 -
    static data member `value` is defined as `true`. Otherwise, `value` is
285 +
    call to @ref value_from, the static data member `value`
 
286 +
    is defined as `true`. Otherwise, `value` is
155  
    defined as `false`.
287  
    defined as `false`.
156  

288  

157 -
    @see @ref value_from.
289 +
    @see @ref value_from
158  
*/
290  
*/
159  
#ifdef BOOST_JSON_DOCS
291  
#ifdef BOOST_JSON_DOCS
160  
template<class T>
292  
template<class T>
161  
using has_value_from = __see_below__;
293  
using has_value_from = __see_below__;
162  
#else
294  
#else
163  
template<class T>
295  
template<class T>
164  
using has_value_from = detail::can_convert<
296  
using has_value_from = detail::can_convert<
165  
    detail::remove_cvref<T>, detail::value_from_conversion>;
297  
    detail::remove_cvref<T>, detail::value_from_conversion>;
166  
#endif
298  
#endif
167  

299  

168  
} // namespace json
300  
} // namespace json
169  
} // namespace boost
301  
} // namespace boost
170  

302  

171  
#endif
303  
#endif