value_to.hpp 7.0 KB

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