conversion.hpp 13 KB

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