conversion.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. //
  2. // Copyright (c) 2022 Dmitry Arkhipov (grisumbras@yandex.ru)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // Official repository: https://github.com/boostorg/json
  8. //
  9. #ifndef BOOST_JSON_CONVERSION_HPP
  10. #define BOOST_JSON_CONVERSION_HPP
  11. #include <boost/json/detail/config.hpp>
  12. #include <boost/json/fwd.hpp>
  13. #include <type_traits>
  14. namespace boost {
  15. namespace json {
  16. namespace detail {
  17. template< class Ctx, class T, class Dir >
  18. struct supported_context;
  19. } // namespace detail
  20. /** Customization point tag.
  21. This tag type is used by the function @ref value_from to select overloads
  22. of `tag_invoke`.
  23. @note This type is empty; it has no members.
  24. @see
  25. @ref value_from, @ref value_to, @ref value_to_tag,
  26. [tag_invoke: A general pattern for supporting customisable functions](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1895r0.pdf).
  27. */
  28. struct value_from_tag { };
  29. /** Customization point tag type.
  30. This tag type is used by the function @ref value_to to select overloads of
  31. `tag_invoke`.
  32. @note This type is empty; it has no members.
  33. @see
  34. @ref value_from, @ref value_from_tag, @ref value_to,
  35. [tag_invoke: A general pattern for supporting customisable functions](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1895r0.pdf).
  36. */
  37. template<class T>
  38. struct value_to_tag { };
  39. /** Customization point tag type.
  40. This tag type is used by the function @ref try_value_to to select overloads
  41. of `tag_invoke`.
  42. @note This type is empty; it has no members.
  43. @see
  44. @ref value_to, @ref value_to_tag,
  45. [tag_invoke: A general pattern for supporting customisable functions](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1895r0.pdf).
  46. */
  47. template<class T>
  48. struct try_value_to_tag { };
  49. /** Determine if `T` can be treated like a string during conversions.
  50. Provides the member constant `value` that is equal to `true`, if `T` is
  51. convertible to @ref string_view. Otherwise, `value` is equal to `false`.
  52. Users can specialize the trait for their own types if they don't want them
  53. to be treated like strings. For example:
  54. @code
  55. namespace boost {
  56. namespace json {
  57. template <>
  58. struct is_string_like<your::string> : std::false_type
  59. { };
  60. } // namespace boost
  61. } // namespace json
  62. @endcode
  63. @par Types satisfying the trait
  64. @ref string, @ref string_view, @ref std::string, @ref std::string_view.
  65. @see @ref value_from, @ref value_to.
  66. */
  67. template<class T>
  68. struct is_string_like;
  69. /** Determine if `T` can be treated like `std::filesystem::path` during conversions.
  70. Given `t`, a glvalue of type `T`, if
  71. - given `It`, the type denoted by `decltype(std::begin(t))`,
  72. `std::iterator_traits<It>::iterator_category` is well-formed and denotes
  73. a type; and
  74. - `std::iterator_traits<It>::value_type` is `T`; and
  75. - `T::value_type` is well-formed and denotes a type; and
  76. - `T::string_type` is well-formed, denotes a type, and is an alias for
  77. `std::basic_string< T::value_type >`;
  78. then the trait provides the member constant `value` that is equal to
  79. `true`. Otherwise, `value` is equal to `false`.
  80. Users can specialize the trait for their own types if they don't want them
  81. to be treated like filesystem paths. For example:
  82. @code
  83. namespace boost {
  84. namespace json {
  85. template <>
  86. struct is_path_like<your::path> : std::false_type
  87. { };
  88. } // namespace boost
  89. } // namespace json
  90. @endcode
  91. @par Types Satisfying the Trait
  92. @ref std::filesystem::path, @ref boost::filesystem::path.
  93. @see @ref value_from, @ref value_to.
  94. */
  95. template<class T>
  96. struct is_path_like;
  97. /** Determine if `T` can be treated like a sequence during conversions.
  98. Given `t`, a glvalue of type `T`, if
  99. - given `It`, the type denoted by `decltype(std::begin(t))`,
  100. `std::iterator_traits<It>::iterator_category` is well-formed and denotes
  101. a type; and
  102. - `decltype(std::end(t))` also denotes the type `It`; and
  103. - `std::iterator_traits<It>::value_type` is not `T`; and
  104. then the trait provides the member constant `value` that is equal to
  105. `true`. Otherwise, `value` is equal to `false`.
  106. Users can specialize the trait for their own types if they don't want them
  107. to be treated like sequences. For example:
  108. @code
  109. namespace boost {
  110. namespace json {
  111. template <>
  112. struct is_sequence_like<your::container> : std::false_type
  113. { };
  114. } // namespace boost
  115. } // namespace json
  116. @endcode
  117. @par Types satisfying the trait
  118. Any {req_SequenceContainer}, array types.
  119. @see @ref value_from, @ref value_to
  120. */
  121. template<class T>
  122. struct is_sequence_like;
  123. /** Determine if `T` can be treated like a 1-to-1 mapping during
  124. conversions.
  125. Given `t`, a glvalue of type `T`, if
  126. - `is_sequence_like<T>::value` is `true`; and
  127. - given type `It` denoting `decltype(std::begin(t))`, and types `K` and
  128. `M`, `std::iterator_traits<It>::value_type` denotes `std::pair<K, M>`;
  129. and
  130. - `std::is_string_like<K>::value` is `true`; and
  131. - given `v`, a glvalue of type `V`, and `E`, the type denoted by
  132. `decltype(t.emplace(v))`, `std::is_tuple_like<E>::value` is `true`;
  133. then the trait provides the member constant `value` that is equal to
  134. `true`. Otherwise, `value` is equal to `false`.
  135. Users can specialize the trait for their own types if they don't want them
  136. to be treated like mappings. For example:
  137. @code
  138. namespace boost {
  139. namespace json {
  140. template <>
  141. struct is_map_like<your::map> : std::false_type
  142. { };
  143. } // namespace boost
  144. } // namespace json
  145. @endcode
  146. @note The restriction for `t.emplace()` return type ensures that the
  147. container does not accept duplicate keys.
  148. @par Types Satisfying The Trait
  149. @ref std::map, @ref std::unordered_map.
  150. @see @ref value_from, @ref value_to.
  151. */
  152. template<class T>
  153. struct is_map_like;
  154. /** Determine if `T` can be treated like a tuple during conversions.
  155. Provides the member constant `value` that is equal to `true`, if
  156. `std::tuple_size<T>::value` is a positive number. Otherwise, `value`
  157. is equal to `false`.
  158. Users can specialize the trait for their own types if they don't want them
  159. to be treated like tuples. For example:
  160. @code
  161. namespace boost {
  162. namespace json {
  163. template <>
  164. struct is_tuple_like<your::tuple> : std::false_type
  165. { };
  166. } // namespace boost
  167. } // namespace json
  168. @endcode
  169. @par Types satisfying the trait
  170. @ref std::tuple, @ref std::pair.
  171. @see @ref value_from, @ref value_to.
  172. */
  173. template<class T>
  174. struct is_tuple_like;
  175. /** Determine if `T` can be treated like null during conversions.
  176. Primary template instantiations provide the member constant `value` that is
  177. equal to `false`. Users can specialize the trait for their own types if
  178. they **do** want them to be treated as nulls. For example:
  179. @code
  180. namespace boost {
  181. namespace json {
  182. template <>
  183. struct is_null_like<your::null_type> : std::true_type
  184. { };
  185. } // namespace boost
  186. } // namespace json
  187. @endcode
  188. @par Types Satisfying the Trait
  189. @ref std::nullptr_t.
  190. @see @ref value_from, @ref value_to
  191. */
  192. template<class T>
  193. struct is_null_like
  194. : std::false_type
  195. { };
  196. /** Determine if `T` should be treated as a described class.
  197. Described classes are serialised as objects with an element for each
  198. described data member. Described bases are serialized in a flattened way,
  199. that is members of bases are serialized as direct elements of the object,
  200. and no nested objects are created for bases.
  201. A described class should not have non-public described members (including
  202. inherited members) or non-public non-empty described bases. Or more
  203. formally, given `L`, a class template of the form
  204. `template<class...> struct L {}`, if
  205. - `boost::describe::has_describe_members<T>::value` is `true`; and
  206. - `boost::describe::describe_members<T, boost::describe::mod_private |
  207. boost::describe::mod_protected | boost::describe::mod_inherited>` denotes
  208. `L<>`; and
  209. - `std::is_union<T>::value` is `false`;
  210. then the trait provides the member constant `value` that is equal to
  211. `true`. Otherwise, `value` is equal to `false`.
  212. @note Shadowed members are ignored both for requirements checking and for
  213. performing conversions.
  214. Users can specialize the trait for their own types if they don't want them
  215. to be treated as described classes. For example:
  216. @code
  217. namespace boost {
  218. namespace json {
  219. template <>
  220. struct is_described_class<your::described_class> : std::false_type
  221. { };
  222. } // namespace boost
  223. } // namespace json
  224. @endcode
  225. Users can also specialize the trait for their own types _with_ described
  226. non-public data members to enable this conversion implementation. Note that
  227. non-public bases are not supported regardless.
  228. @see [Boost.Describe](https://www.boost.org/doc/libs/latest/libs/describe/doc/html/describe.html).
  229. */
  230. template<class T>
  231. struct is_described_class;
  232. /** Determine if `T` should be treated as a described enum.
  233. Described enums are serialised as strings when their value equals to a
  234. described enumerator, and as integers otherwise. The reverse operation
  235. does not convert numbers to enums values, though, and instead produces
  236. an error.
  237. If `boost::describe::has_describe_enumerators<T>::value` is `true`, then
  238. the trait provides the member constant `value` that is equal to `true`.
  239. Otherwise, `value` is equal to `false`.
  240. Users can specialize the trait for their own enums if they don't want them
  241. to be treated as described enums. For example:
  242. @code
  243. namespace boost {
  244. namespace json {
  245. template <>
  246. struct is_described_enum<your::described_enum> : std::false_type
  247. { };
  248. } // namespace boost
  249. } // namespace json
  250. @endcode
  251. @see [Boost.Describe](https://www.boost.org/doc/libs/latest/libs/describe/doc/html/describe.html).
  252. */
  253. template<class T>
  254. struct is_described_enum;
  255. /** Determine if `T` should be treated as a variant.
  256. Variants are serialised the same way their active alternative is
  257. serialised. The opposite conversion selects the first alternative for which
  258. conversion succeeds.
  259. Given `t`, a glvalue of type ` const T`, if `t.valueless_by_exception()` is
  260. well-formed, then the trait provides the member constant `value` that is
  261. equal to `true`. Otherwise, `value` is equal to `false`.
  262. Users can specialize the trait for their own types if they don't want them
  263. to be treated as variants. For example:
  264. @code
  265. namespace boost {
  266. namespace json {
  267. template <>
  268. struct is_variant_like<your::variant> : std::false_type
  269. { };
  270. } // namespace boost
  271. } // namespace json
  272. @endcode
  273. @par Types Satisfying the Trait
  274. @ref std::variant, @ref boost::variant2::variant.
  275. */
  276. template<class T>
  277. struct is_variant_like;
  278. /** Determine if `T` should be treated as an optional
  279. Optionals are serialised as `null` if empty, or as the stored type
  280. otherwise.
  281. Given `t`, a glvalue of type `T`, if
  282. - `decltype( t.value() )` is well-formed and isn't a void type; and
  283. - `t.reset()` is well-formed;
  284. then the trait provides the member constant `value` that is equal to
  285. `true`. Otherwise, `value` is equal to `false`.
  286. Users can specialize the trait for their own types if they don't want them
  287. to be treated as optionals. For example:
  288. @code
  289. namespace boost {
  290. namespace json {
  291. template <>
  292. struct is_optional_like<your::optional> : std::false_type
  293. { };
  294. } // namespace boost
  295. } // namespace json
  296. @endcode
  297. @par Types Satisfying the Trait
  298. @ref std::optional, @ref boost::optional.
  299. */
  300. template<class T>
  301. struct is_optional_like;
  302. } // namespace json
  303. } // namespace boost
  304. #include <boost/json/impl/conversion.hpp>
  305. #endif // BOOST_JSON_CONVERSION_HPP