diff --git a/src/json.hpp b/src/json.hpp index 2bc35c4a..06c5683b 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -956,6 +956,8 @@ default; will be used in @ref number_integer_t) default; will be used in @ref number_float_t) @tparam AllocatorType type of the allocator to use (`std::allocator` by default) +@tparam JSONSerializer the serializer to resolve internal calls to `to_json()` +and `from_json()` @requirement The class satisfies the following concept requirements: - Basic @@ -2997,6 +2999,10 @@ class basic_json /// @} private: + ////////////////// + // value access // + ////////////////// + /// get a boolean (explicit) boolean_t get_impl(boolean_t* /*unused*/) const { @@ -3124,12 +3130,17 @@ class basic_json } public: + /// @name value access + /// Direct access to the stored value of a JSON value. + /// @{ + /*! @brief get special-case overload - This overloads avoids a lot of template boilerplate, it can be seen as the identity method + This overloads avoids a lot of template boilerplate, it can be seen as the + identity method - @tparam T type; T == @ref basic_json + @tparam BasicJsonType == @ref basic_json @return a copy of *this @@ -3138,8 +3149,8 @@ class basic_json @since version 2.1.0 */ template < - typename T, - detail::enable_if_t::type, + typename BasicJsonType, + detail::enable_if_t::type, basic_json_t>::value, int> = 0 > basic_json get() const @@ -3148,66 +3159,111 @@ class basic_json } /*! - @brief get overload for CopyConstructible and DefaultConstructible types - construct a default U value, and call @ref json_serializer from_json method with it + @brief get a value (explicit) + + Explicit type conversion between the JSON value and a compatible value + which is [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible) + and [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible). + The value is converted by calling the @ref json_serializer + `from_json()` method. + + The function is equivalent to executing + @code {.cpp} + ValueType ret; + JSONSerializer::from_json(*this, ret); + return ret; + @endcode This overloads is chosen if: - - U is not @ref basic_json - - @ref json_serializer has a from_json method of the form: void from_json(const @ref basic_json&, U&) - - @ref json_serializer does not have a from_json method of the form: U from_json(const @ref basic_json&); + - @a ValueType is not @ref basic_json, + - @ref json_serializer has a `from_json()` method of the form + `void from_json(const @ref basic_json&, ValueType&)`, and + - @ref json_serializer does not have a `from_json()` method of + the form `ValueType from_json(const @ref basic_json&)` - @return a value of type U + @tparam ValueTypeCV the provided value type + @tparam ValueType the returned value type - @throw what json_serializer from_json method throws + @return copy of the JSON value, converted to @a ValueType + + @throw what @ref json_serializer `from_json()` method throws + + @liveexample{The example below shows several conversions from JSON values + to other types. There a few things to note: (1) Floating-point numbers can + be converted to integers\, (2) A JSON array can be converted to a standard + `std::vector`\, (3) A JSON object can be converted to C++ + associative containers such as `std::unordered_map`.,get__ValueType_const} @since version 2.1.0 */ template < - typename T, - typename U = detail::uncvref_t, + typename ValueTypeCV, + typename ValueType = detail::uncvref_t, detail::enable_if_t < - not std::is_same::value and - detail::has_from_json::value and - not detail::has_non_default_from_json::value, + not std::is_same::value and + detail::has_from_json::value and + not detail::has_non_default_from_json::value, int > = 0 > - U get() const noexcept(noexcept(JSONSerializer::from_json( - std::declval(), std::declval()))) + ValueType get() const noexcept(noexcept( + JSONSerializer::from_json(std::declval(), std::declval()))) { - // we cannot static_assert on T being non-const, because there is support - // for get(), which is why we still need the uncvref - static_assert(not std::is_reference::value, "get cannot be used with reference types, you might want to use get_ref"); - static_assert(std::is_default_constructible::value, - "Types must be DefaultConstructible when used with get"); - U ret; - JSONSerializer::from_json(*this, ret); + // we cannot static_assert on ValueTypeCV being non-const, because + // there is support for get(), which is why we + // still need the uncvref + static_assert(not std::is_reference::value, + "get() cannot be used with reference types, you might want to use get_ref()"); + static_assert(std::is_default_constructible::value, + "types must be DefaultConstructible when used with get()"); + + ValueType ret; + JSONSerializer::from_json(*this, ret); return ret; } /*! - @brief get overload for types than cannot be default constructed or copy constructed + @brief get a value (explicit); special case - If @ref json_serializer has both overloads of from_json, this one is chosen + Explicit type conversion between the JSON value and a compatible value + which is **not** [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible) + and **not** [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible). + The value is converted by calling the @ref json_serializer + `from_json()` method. + + The function is equivalent to executing + @code {.cpp} + return JSONSerializer::from_json(*this); + @endcode This overloads is chosen if: - - U is not @ref basic_json - - @ref json_serializer has a from_json method of the form: U from_json(const @ref basic_json&); + - @a ValueType is not @ref basic_json and + - @ref json_serializer has a `from_json()` method of the form + `ValueType from_json(const @ref basic_json&)` - @return a value of type U + @note If @ref json_serializer has both overloads of + `from_json()`, this one is chosen. - @throw what json_serializer from_json method throws + @tparam ValueTypeCV the provided value type + @tparam ValueType the returned value type + + @return copy of the JSON value, converted to @a ValueType + + @throw what @ref json_serializer `from_json()` method throws @since version 2.1.0 */ template < - typename T, - typename U = detail::uncvref_t, - detail::enable_if_t::value and + typename ValueTypeCV, + typename ValueType = detail::uncvref_t, + detail::enable_if_t::value and detail::has_non_default_from_json::value, int> = 0 > - U get() const noexcept(noexcept(JSONSerializer::from_json(std::declval()))) + ValueType>::value, int> = 0 > + ValueType get() const noexcept(noexcept( + JSONSerializer::from_json(std::declval()))) { - static_assert(not std::is_reference::value, "get cannot be used with reference types, you might want to use get_ref"); - return JSONSerializer::from_json(*this); + static_assert(not std::is_reference::value, + "get() cannot be used with reference types, you might want to use get_ref()"); + return JSONSerializer::from_json(*this); } /*! diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 5a9d2f88..0bf3db1d 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -956,6 +956,8 @@ default; will be used in @ref number_integer_t) default; will be used in @ref number_float_t) @tparam AllocatorType type of the allocator to use (`std::allocator` by default) +@tparam JSONSerializer the serializer to resolve internal calls to `to_json()` +and `from_json()` @requirement The class satisfies the following concept requirements: - Basic @@ -2997,6 +2999,10 @@ class basic_json /// @} private: + ////////////////// + // value access // + ////////////////// + /// get a boolean (explicit) boolean_t get_impl(boolean_t* /*unused*/) const { @@ -3124,12 +3130,17 @@ class basic_json } public: + /// @name value access + /// Direct access to the stored value of a JSON value. + /// @{ + /*! @brief get special-case overload - This overloads avoids a lot of template boilerplate, it can be seen as the identity method + This overloads avoids a lot of template boilerplate, it can be seen as the + identity method - @tparam T type; T == @ref basic_json + @tparam BasicJsonType == @ref basic_json @return a copy of *this @@ -3138,8 +3149,8 @@ class basic_json @since version 2.1.0 */ template < - typename T, - detail::enable_if_t::type, + typename BasicJsonType, + detail::enable_if_t::type, basic_json_t>::value, int> = 0 > basic_json get() const @@ -3148,66 +3159,111 @@ class basic_json } /*! - @brief get overload for CopyConstructible and DefaultConstructible types - construct a default U value, and call @ref json_serializer from_json method with it + @brief get a value (explicit) + + Explicit type conversion between the JSON value and a compatible value + which is [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible) + and [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible). + The value is converted by calling the @ref json_serializer + `from_json()` method. + + The function is equivalent to executing + @code {.cpp} + ValueType ret; + JSONSerializer::from_json(*this, ret); + return ret; + @endcode This overloads is chosen if: - - U is not @ref basic_json - - @ref json_serializer has a from_json method of the form: void from_json(const @ref basic_json&, U&) - - @ref json_serializer does not have a from_json method of the form: U from_json(const @ref basic_json&); + - @a ValueType is not @ref basic_json, + - @ref json_serializer has a `from_json()` method of the form + `void from_json(const @ref basic_json&, ValueType&)`, and + - @ref json_serializer does not have a `from_json()` method of + the form `ValueType from_json(const @ref basic_json&)` - @return a value of type U + @tparam ValueTypeCV the provided value type + @tparam ValueType the returned value type - @throw what json_serializer from_json method throws + @return copy of the JSON value, converted to @a ValueType + + @throw what @ref json_serializer `from_json()` method throws + + @liveexample{The example below shows several conversions from JSON values + to other types. There a few things to note: (1) Floating-point numbers can + be converted to integers\, (2) A JSON array can be converted to a standard + `std::vector`\, (3) A JSON object can be converted to C++ + associative containers such as `std::unordered_map`.,get__ValueType_const} @since version 2.1.0 */ template < - typename T, - typename U = detail::uncvref_t, + typename ValueTypeCV, + typename ValueType = detail::uncvref_t, detail::enable_if_t < - not std::is_same::value and - detail::has_from_json::value and - not detail::has_non_default_from_json::value, + not std::is_same::value and + detail::has_from_json::value and + not detail::has_non_default_from_json::value, int > = 0 > - U get() const noexcept(noexcept(JSONSerializer::from_json( - std::declval(), std::declval()))) + ValueType get() const noexcept(noexcept( + JSONSerializer::from_json(std::declval(), std::declval()))) { - // we cannot static_assert on T being non-const, because there is support - // for get(), which is why we still need the uncvref - static_assert(not std::is_reference::value, "get cannot be used with reference types, you might want to use get_ref"); - static_assert(std::is_default_constructible::value, - "Types must be DefaultConstructible when used with get"); - U ret; - JSONSerializer::from_json(*this, ret); + // we cannot static_assert on ValueTypeCV being non-const, because + // there is support for get(), which is why we + // still need the uncvref + static_assert(not std::is_reference::value, + "get() cannot be used with reference types, you might want to use get_ref()"); + static_assert(std::is_default_constructible::value, + "types must be DefaultConstructible when used with get()"); + + ValueType ret; + JSONSerializer::from_json(*this, ret); return ret; } /*! - @brief get overload for types than cannot be default constructed or copy constructed + @brief get a value (explicit); special case - If @ref json_serializer has both overloads of from_json, this one is chosen + Explicit type conversion between the JSON value and a compatible value + which is **not** [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible) + and **not** [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible). + The value is converted by calling the @ref json_serializer + `from_json()` method. + + The function is equivalent to executing + @code {.cpp} + return JSONSerializer::from_json(*this); + @endcode This overloads is chosen if: - - U is not @ref basic_json - - @ref json_serializer has a from_json method of the form: U from_json(const @ref basic_json&); + - @a ValueType is not @ref basic_json and + - @ref json_serializer has a `from_json()` method of the form + `ValueType from_json(const @ref basic_json&)` - @return a value of type U + @note If @ref json_serializer has both overloads of + `from_json()`, this one is chosen. - @throw what json_serializer from_json method throws + @tparam ValueTypeCV the provided value type + @tparam ValueType the returned value type + + @return copy of the JSON value, converted to @a ValueType + + @throw what @ref json_serializer `from_json()` method throws @since version 2.1.0 */ template < - typename T, - typename U = detail::uncvref_t, - detail::enable_if_t::value and + typename ValueTypeCV, + typename ValueType = detail::uncvref_t, + detail::enable_if_t::value and detail::has_non_default_from_json::value, int> = 0 > - U get() const noexcept(noexcept(JSONSerializer::from_json(std::declval()))) + ValueType>::value, int> = 0 > + ValueType get() const noexcept(noexcept( + JSONSerializer::from_json(std::declval()))) { - static_assert(not std::is_reference::value, "get cannot be used with reference types, you might want to use get_ref"); - return JSONSerializer::from_json(*this); + static_assert(not std::is_reference::value, + "get() cannot be used with reference types, you might want to use get_ref()"); + return JSONSerializer::from_json(*this); } /*!