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 function supports default constructible types satisfying
33  
    {req_SequenceContainer}, arrays, arithmetic types, `bool`, `std::tuple`,
32  
    {req_SequenceContainer}, arrays, arithmetic types, `bool`, `std::tuple`,
34  
    `std::pair`, `std::optional`, `std::variant`, `std::nullptr_t`, and structs
33  
    `std::pair`, `std::optional`, `std::variant`, `std::nullptr_t`, and structs
35  
    and enums described using Boost.Describe.
34  
    and enums described using Boost.Describe.
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  

61  

63  
    Overloads **(2)** and **(4)** construct their return value using the
62  
    Overloads **(2)** and **(4)** construct their return value using the
64  
    @ref storage_ptr `sp`, which ensures that the memory resource is correctly
63  
    @ref storage_ptr `sp`, which ensures that the memory resource is correctly
65  
    propagated.
64  
    propagated.
66  

65  

67  
    @par Exception Safety
66  
    @par Exception Safety
68  
    Strong guarantee.
67  
    Strong guarantee.
69  

68  

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

70  

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

72  

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

74  

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

76  

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

78  

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

97  

100  
/** Overload
98  
/** Overload
101  
   @param t
99  
   @param t
102  
   @param ctx
100  
   @param ctx
103  
   @param sp A storage pointer referring to the memory resource to use for the
101  
   @param sp A storage pointer referring to the memory resource to use for the
104  
   returned @ref value.
102  
   returned @ref value.
105  

103  

106  
   @return Overloads **(2)** and **(4)** return `t` converted to @ref value.
104  
   @return Overloads **(2)** and **(4)** return `t` converted to @ref value.
107  
   Overloads **(1)** and **3** return `void` instead and pass their result via
105  
   Overloads **(1)** and **3** return `void` instead and pass their result via
108  
   the out parameter `jv`.
106  
   the out parameter `jv`.
109  
*/
107  
*/
110  
template< class T, class Context >
108  
template< class T, class Context >
111  
#ifndef BOOST_JSON_DOCS
109  
#ifndef BOOST_JSON_DOCS
112  
typename std::enable_if<
110  
typename std::enable_if<
113  
    !std::is_same< detail::remove_cvref<Context>, storage_ptr >::value &&
111  
    !std::is_same< detail::remove_cvref<Context>, storage_ptr >::value &&
114  
    !std::is_same< detail::remove_cvref<Context>, value >::value,
112  
    !std::is_same< detail::remove_cvref<Context>, value >::value,
115  
    value >::type
113  
    value >::type
116  
#else
114  
#else
117  
value
115  
value
118  
#endif
116  
#endif
119  
value_from(
117  
value_from(
120  
    T&& t,
118  
    T&& t,
121  
    Context const& ctx,
119  
    Context const& ctx,
122  
    storage_ptr sp = {})
120  
    storage_ptr sp = {})
123  
{
121  
{
124  
    value jv(std::move(sp));
122  
    value jv(std::move(sp));
125  
    value_from( static_cast<T&&>(t), ctx, jv );
123  
    value_from( static_cast<T&&>(t), ctx, jv );
126  
    return jv;
124  
    return jv;
127  
}
125  
}
128  

126  

129  
/// Overload
127  
/// Overload
130  
template<class T>
128  
template<class T>
131  
void
129  
void
132  
value_from(
130  
value_from(
133  
    T&& t,
131  
    T&& t,
134  
    value& jv)
132  
    value& jv)
135  
{
133  
{
136  
   value_from( static_cast<T&&>(t), detail::no_context(), jv );
134  
   value_from( static_cast<T&&>(t), detail::no_context(), jv );
137  
}
135  
}
138  

136  

139  
/// Overload
137  
/// Overload
140  
template<class T>
138  
template<class T>
141  
value
139  
value
142  
value_from(
140  
value_from(
143  
    T&& t,
141  
    T&& t,
144  
    storage_ptr sp = {})
142  
    storage_ptr sp = {})
145  
{
143  
{
146  
   return value_from(
144  
   return value_from(
147  
           static_cast<T&&>(t), detail::no_context(), std::move(sp) );
145  
           static_cast<T&&>(t), detail::no_context(), std::move(sp) );
148  
}
146  
}
149  
/// @}
147  
/// @}
150  

148  

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

150  

153  
    If `T` can be converted to @ref value via a call to @ref value_from, the
151  
    If `T` can be converted to @ref value via a call to @ref value_from, the
154  
    static data member `value` is defined as `true`. Otherwise, `value` is
152  
    static data member `value` is defined as `true`. Otherwise, `value` is
155  
    defined as `false`.
153  
    defined as `false`.
156  

154  

157  
    @see @ref value_from.
155  
    @see @ref value_from.
158  
*/
156  
*/
159  
#ifdef BOOST_JSON_DOCS
157  
#ifdef BOOST_JSON_DOCS
160  
template<class T>
158  
template<class T>
161  
using has_value_from = __see_below__;
159  
using has_value_from = __see_below__;
162  
#else
160  
#else
163  
template<class T>
161  
template<class T>
164  
using has_value_from = detail::can_convert<
162  
using has_value_from = detail::can_convert<
165  
    detail::remove_cvref<T>, detail::value_from_conversion>;
163  
    detail::remove_cvref<T>, detail::value_from_conversion>;
166  
#endif
164  
#endif
167  

165  

168  
} // namespace json
166  
} // namespace json
169  
} // namespace boost
167  
} // namespace boost
170  

168  

171  
#endif
169  
#endif