value_from.hpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  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_FROM_HPP
  12. #define BOOST_JSON_VALUE_FROM_HPP
  13. #include <boost/core/detail/static_assert.hpp>
  14. #include <boost/json/detail/value_from.hpp>
  15. namespace boost {
  16. namespace json {
  17. /** Convert an object of type `T` to @ref value.
  18. This function attempts to convert an object
  19. of type `T` to @ref value using
  20. @li one of @ref value's constructors,
  21. @li a library-provided generic conversion, or
  22. @li a user-provided overload of `tag_invoke`.
  23. Out of 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. void tag_invoke( value_from_tag, value&, T, const Context&, const FullContext& );
  32. @endcode
  33. or
  34. @code
  35. void tag_invoke( value_from_tag, value&, T, const Context& );
  36. @endcode
  37. or
  38. @code
  39. void tag_invoke( value_from_tag, value&, T );
  40. @endcode
  41. The overloads are checked for existence in that order and the first that
  42. matches will be selected. <br>
  43. The `ctx` argument can be used either as a tag type to provide conversions
  44. for third-party types, or to pass extra data to the conversion function.
  45. Overloads **(2)** and **(4)** construct their return value using the
  46. @ref storage_ptr `sp`, which ensures that the memory resource is correctly
  47. propagated.
  48. @par Exception Safety
  49. Strong guarantee.
  50. @tparam T The type of the object to convert.
  51. @tparam Context The type of context passed to the conversion function.
  52. @param t The object to convert.
  53. @param ctx Context passed to the conversion function.
  54. @param jv @ref value out parameter.
  55. @see @ref value_from_tag, @ref value_to,
  56. <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1895r0.pdf">
  57. tag_invoke: A general pattern for supporting customisable functions</a>
  58. */
  59. /// @{
  60. template< class T, class Context >
  61. void
  62. value_from(
  63. T&& t,
  64. Context const& ctx,
  65. value& jv)
  66. {
  67. using bare_T = detail::remove_cvref<T>;
  68. BOOST_CORE_STATIC_ASSERT((
  69. detail::conversion_round_trips<
  70. Context, bare_T, detail::value_from_conversion>::value));
  71. using cat = detail::value_from_category<Context, bare_T>;
  72. detail::value_from_impl( cat(), jv, std::forward<T>(t), ctx );
  73. }
  74. /** Overload
  75. @param t
  76. @param ctx
  77. @param sp A storage pointer referring to the memory resource to use for the
  78. returned @ref value.
  79. @return Overloads **(2)** and **(4)** return `t` converted to @ref value.
  80. Overloads **(1)** and **3** return `void` instead and pass their result via
  81. the out parameter `jv`.
  82. */
  83. template< class T, class Context >
  84. #ifndef BOOST_JSON_DOCS
  85. typename std::enable_if<
  86. !std::is_same< detail::remove_cvref<Context>, storage_ptr >::value &&
  87. !std::is_same< detail::remove_cvref<Context>, value >::value,
  88. value >::type
  89. #else
  90. value
  91. #endif
  92. value_from(
  93. T&& t,
  94. Context const& ctx,
  95. storage_ptr sp = {})
  96. {
  97. value jv(std::move(sp));
  98. value_from( static_cast<T&&>(t), ctx, jv );
  99. return jv;
  100. }
  101. /// Overload
  102. template<class T>
  103. void
  104. value_from(
  105. T&& t,
  106. value& jv)
  107. {
  108. value_from( static_cast<T&&>(t), detail::no_context(), jv );
  109. }
  110. /// Overload
  111. template<class T>
  112. value
  113. value_from(
  114. T&& t,
  115. storage_ptr sp = {})
  116. {
  117. return value_from(
  118. static_cast<T&&>(t), detail::no_context(), std::move(sp) );
  119. }
  120. /// @}
  121. /** Determine if `T` can be converted to @ref value.
  122. If `T` can be converted to @ref value via a call to @ref value_from, the
  123. static data member `value` is defined as `true`. Otherwise, `value` is
  124. defined as `false`.
  125. @see @ref value_from.
  126. */
  127. #ifdef BOOST_JSON_DOCS
  128. template<class T>
  129. using has_value_from = __see_below__;
  130. #else
  131. template<class T>
  132. using has_value_from = detail::can_convert<
  133. detail::remove_cvref<T>, detail::value_from_conversion>;
  134. #endif
  135. } // namespace json
  136. } // namespace boost
  137. #endif