cleanup after #184
This commit is contained in:
parent
663ad13fc3
commit
a04bd4f851
7 changed files with 103 additions and 58 deletions
|
@ -382,7 +382,7 @@ I deeply appreciate the help of the following people.
|
||||||
- [Colin Hirsch](https://github.com/ColinH) took care of a small namespace issue.
|
- [Colin Hirsch](https://github.com/ColinH) took care of a small namespace issue.
|
||||||
- [Huu Nguyen](https://github.com/whoshuu) correct a variable name in the documentation.
|
- [Huu Nguyen](https://github.com/whoshuu) correct a variable name in the documentation.
|
||||||
- [Silverweed](https://github.com/silverweed) overloaded `parse()` to accept an rvalue reference.
|
- [Silverweed](https://github.com/silverweed) overloaded `parse()` to accept an rvalue reference.
|
||||||
- [dariomt](https://github.com/dariomt) fixed a subtlety in MSVC type support.
|
- [dariomt](https://github.com/dariomt) fixed a subtlety in MSVC type support and implemented the `get_ref()` function to get a reference to stored values.
|
||||||
- [ZahlGraf](https://github.com/ZahlGraf) added a workaround that allows compilation using Android NDK.
|
- [ZahlGraf](https://github.com/ZahlGraf) added a workaround that allows compilation using Android NDK.
|
||||||
- [whackashoe](https://github.com/whackashoe) replaced a function that was marked as unsafe by Visual Studio.
|
- [whackashoe](https://github.com/whackashoe) replaced a function that was marked as unsafe by Visual Studio.
|
||||||
- [406345](https://github.com/406345) fixed two small warnings.
|
- [406345](https://github.com/406345) fixed two small warnings.
|
||||||
|
|
|
@ -19,7 +19,7 @@ int main()
|
||||||
{
|
{
|
||||||
auto r3 = value.get_ref<json::number_float_t&>();
|
auto r3 = value.get_ref<json::number_float_t&>();
|
||||||
}
|
}
|
||||||
catch(std::domain_error& ex)
|
catch (std::domain_error& ex)
|
||||||
{
|
{
|
||||||
std::cout << ex.what() << '\n';
|
std::cout << ex.what() << '\n';
|
||||||
}
|
}
|
||||||
|
|
1
doc/examples/get_ref.link
Normal file
1
doc/examples/get_ref.link
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<a target="_blank" href="http://melpon.org/wandbox/permlink/nBNBANVonG9HCQqQ"><b>online</b></a>
|
2
doc/examples/get_ref.output
Normal file
2
doc/examples/get_ref.output
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
17 17
|
||||||
|
incompatible ReferenceType for get_ref, actual type is number
|
61
src/json.hpp
61
src/json.hpp
|
@ -2416,17 +2416,33 @@ class basic_json
|
||||||
return is_number_float() ? &m_value.number_float : nullptr;
|
return is_number_float() ? &m_value.number_float : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// helper function to implement get_ref without code duplication
|
/*!
|
||||||
/// for const and non-const overloads
|
@brief helper function to implement get_ref()
|
||||||
/// ThisType will be deduced as 'basic_jason' or 'const basic_json'
|
|
||||||
template<typename ReferenceType, typename ThisType>
|
This funcion helps to implement get_ref() without code duplication for
|
||||||
|
const and non-const overloads
|
||||||
|
|
||||||
|
@tparam ThisType will be deduced as `basic_json` or `const basic_json`
|
||||||
|
|
||||||
|
@throw std::domain_error if ReferenceType does not match underlying value
|
||||||
|
type of the current JSON
|
||||||
|
*/
|
||||||
|
template<typename ReferenceType, typename ThisType>
|
||||||
static ReferenceType get_ref_impl(ThisType& obj)
|
static ReferenceType get_ref_impl(ThisType& obj)
|
||||||
{
|
{
|
||||||
using PointerType = typename std::add_pointer<ReferenceType>::type;
|
|
||||||
// delegate the call to get_ptr<>()
|
// delegate the call to get_ptr<>()
|
||||||
|
using PointerType = typename std::add_pointer<ReferenceType>::type;
|
||||||
auto ptr = obj.template get_ptr<PointerType>();
|
auto ptr = obj.template get_ptr<PointerType>();
|
||||||
if (ptr) return *ptr;
|
|
||||||
throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " + obj.type_name());
|
if (ptr != nullptr)
|
||||||
|
{
|
||||||
|
return *ptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " +
|
||||||
|
obj.type_name());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -2576,7 +2592,7 @@ class basic_json
|
||||||
return get_impl_ptr(static_cast<const PointerType>(nullptr));
|
return get_impl_ptr(static_cast<const PointerType>(nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief get a reference value (implicit)
|
@brief get a reference value (implicit)
|
||||||
|
|
||||||
Implict reference access to the internally stored JSON value. No copies are
|
Implict reference access to the internally stored JSON value. No copies are
|
||||||
|
@ -2585,17 +2601,22 @@ class basic_json
|
||||||
@warning Writing data to the referee of the result yields an undefined
|
@warning Writing data to the referee of the result yields an undefined
|
||||||
state.
|
state.
|
||||||
|
|
||||||
@tparam ReferenceType reference type; must be a reference to @ref array_t, @ref
|
@tparam ReferenceType reference type; must be a reference to @ref array_t,
|
||||||
object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or @ref
|
@ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or
|
||||||
number_float_t.
|
@ref number_float_t.
|
||||||
|
|
||||||
@return reference to the internally stored JSON value if the requested reference
|
@return reference to the internally stored JSON value if the requested
|
||||||
type @a ReferenceType fits to the JSON value; throws std::domain_error otherwise
|
reference type @a ReferenceType fits to the JSON value; throws
|
||||||
|
std::domain_error otherwise
|
||||||
|
|
||||||
@throw std::domain_error in case passed type @a ReferenceType is incompatible
|
@throw std::domain_error in case passed type @a ReferenceType is
|
||||||
with the stored JSON value
|
incompatible with the stored JSON value
|
||||||
|
|
||||||
@complexity Constant.
|
@complexity Constant.
|
||||||
|
|
||||||
|
@liveexample{The example shows several calls to `get_ref()`.,get_ref}
|
||||||
|
|
||||||
|
@since version 1.0.1
|
||||||
*/
|
*/
|
||||||
template<typename ReferenceType, typename
|
template<typename ReferenceType, typename
|
||||||
std::enable_if<
|
std::enable_if<
|
||||||
|
@ -2603,8 +2624,8 @@ class basic_json
|
||||||
, int>::type = 0>
|
, int>::type = 0>
|
||||||
ReferenceType get_ref()
|
ReferenceType get_ref()
|
||||||
{
|
{
|
||||||
// delegate call to get_ref_impl
|
// delegate call to get_ref_impl
|
||||||
return get_ref_impl<ReferenceType>(*this);
|
return get_ref_impl<ReferenceType>(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -2614,12 +2635,12 @@ class basic_json
|
||||||
template<typename ReferenceType, typename
|
template<typename ReferenceType, typename
|
||||||
std::enable_if<
|
std::enable_if<
|
||||||
std::is_reference<ReferenceType>::value
|
std::is_reference<ReferenceType>::value
|
||||||
and std::is_const< typename std::remove_reference<ReferenceType>::type >::value
|
and std::is_const<typename std::remove_reference<ReferenceType>::type>::value
|
||||||
, int>::type = 0>
|
, int>::type = 0>
|
||||||
ReferenceType get_ref() const
|
ReferenceType get_ref() const
|
||||||
{
|
{
|
||||||
// delegate call to get_ref_impl
|
// delegate call to get_ref_impl
|
||||||
return get_ref_impl<ReferenceType>(*this);
|
return get_ref_impl<ReferenceType>(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
|
@ -2416,17 +2416,33 @@ class basic_json
|
||||||
return is_number_float() ? &m_value.number_float : nullptr;
|
return is_number_float() ? &m_value.number_float : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// helper function to implement get_ref without code duplication
|
/*!
|
||||||
/// for const and non-const overloads
|
@brief helper function to implement get_ref()
|
||||||
/// ThisType will be deduced as 'basic_jason' or 'const basic_json'
|
|
||||||
template<typename ReferenceType, typename ThisType>
|
This funcion helps to implement get_ref() without code duplication for
|
||||||
|
const and non-const overloads
|
||||||
|
|
||||||
|
@tparam ThisType will be deduced as `basic_json` or `const basic_json`
|
||||||
|
|
||||||
|
@throw std::domain_error if ReferenceType does not match underlying value
|
||||||
|
type of the current JSON
|
||||||
|
*/
|
||||||
|
template<typename ReferenceType, typename ThisType>
|
||||||
static ReferenceType get_ref_impl(ThisType& obj)
|
static ReferenceType get_ref_impl(ThisType& obj)
|
||||||
{
|
{
|
||||||
using PointerType = typename std::add_pointer<ReferenceType>::type;
|
|
||||||
// delegate the call to get_ptr<>()
|
// delegate the call to get_ptr<>()
|
||||||
|
using PointerType = typename std::add_pointer<ReferenceType>::type;
|
||||||
auto ptr = obj.template get_ptr<PointerType>();
|
auto ptr = obj.template get_ptr<PointerType>();
|
||||||
if (ptr) return *ptr;
|
|
||||||
throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " + obj.type_name());
|
if (ptr != nullptr)
|
||||||
|
{
|
||||||
|
return *ptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " +
|
||||||
|
obj.type_name());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -2576,7 +2592,7 @@ class basic_json
|
||||||
return get_impl_ptr(static_cast<const PointerType>(nullptr));
|
return get_impl_ptr(static_cast<const PointerType>(nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief get a reference value (implicit)
|
@brief get a reference value (implicit)
|
||||||
|
|
||||||
Implict reference access to the internally stored JSON value. No copies are
|
Implict reference access to the internally stored JSON value. No copies are
|
||||||
|
@ -2585,17 +2601,22 @@ class basic_json
|
||||||
@warning Writing data to the referee of the result yields an undefined
|
@warning Writing data to the referee of the result yields an undefined
|
||||||
state.
|
state.
|
||||||
|
|
||||||
@tparam ReferenceType reference type; must be a reference to @ref array_t, @ref
|
@tparam ReferenceType reference type; must be a reference to @ref array_t,
|
||||||
object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or @ref
|
@ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or
|
||||||
number_float_t.
|
@ref number_float_t.
|
||||||
|
|
||||||
@return reference to the internally stored JSON value if the requested reference
|
@return reference to the internally stored JSON value if the requested
|
||||||
type @a ReferenceType fits to the JSON value; throws std::domain_error otherwise
|
reference type @a ReferenceType fits to the JSON value; throws
|
||||||
|
std::domain_error otherwise
|
||||||
|
|
||||||
@throw std::domain_error in case passed type @a ReferenceType is incompatible
|
@throw std::domain_error in case passed type @a ReferenceType is
|
||||||
with the stored JSON value
|
incompatible with the stored JSON value
|
||||||
|
|
||||||
@complexity Constant.
|
@complexity Constant.
|
||||||
|
|
||||||
|
@liveexample{The example shows several calls to `get_ref()`.,get_ref}
|
||||||
|
|
||||||
|
@since version 1.0.1
|
||||||
*/
|
*/
|
||||||
template<typename ReferenceType, typename
|
template<typename ReferenceType, typename
|
||||||
std::enable_if<
|
std::enable_if<
|
||||||
|
@ -2603,8 +2624,8 @@ class basic_json
|
||||||
, int>::type = 0>
|
, int>::type = 0>
|
||||||
ReferenceType get_ref()
|
ReferenceType get_ref()
|
||||||
{
|
{
|
||||||
// delegate call to get_ref_impl
|
// delegate call to get_ref_impl
|
||||||
return get_ref_impl<ReferenceType>(*this);
|
return get_ref_impl<ReferenceType>(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -2614,12 +2635,12 @@ class basic_json
|
||||||
template<typename ReferenceType, typename
|
template<typename ReferenceType, typename
|
||||||
std::enable_if<
|
std::enable_if<
|
||||||
std::is_reference<ReferenceType>::value
|
std::is_reference<ReferenceType>::value
|
||||||
and std::is_const< typename std::remove_reference<ReferenceType>::type >::value
|
and std::is_const<typename std::remove_reference<ReferenceType>::type>::value
|
||||||
, int>::type = 0>
|
, int>::type = 0>
|
||||||
ReferenceType get_ref() const
|
ReferenceType get_ref() const
|
||||||
{
|
{
|
||||||
// delegate call to get_ref_impl
|
// delegate call to get_ref_impl
|
||||||
return get_ref_impl<ReferenceType>(*this);
|
return get_ref_impl<ReferenceType>(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
|
@ -2604,13 +2604,13 @@ TEST_CASE("pointer access")
|
||||||
CHECK(value.get_ptr<json::number_float_t*>() == nullptr);
|
CHECK(value.get_ptr<json::number_float_t*>() == nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("pointer access to const object_t")
|
SECTION("pointer access to const object_t")
|
||||||
{
|
{
|
||||||
using test_type = json::object_t;
|
using test_type = json::object_t;
|
||||||
const json value = {{"one", 1}, {"two", 2}};
|
const json value = {{"one", 1}, {"two", 2}};
|
||||||
|
|
||||||
// this should not compile
|
// this should not compile
|
||||||
// test_type* p1 = value.get_ptr<test_type*>();
|
// test_type* p1 = value.get_ptr<test_type*>();
|
||||||
|
|
||||||
// check if pointers are returned correctly
|
// check if pointers are returned correctly
|
||||||
const test_type* p2 = value.get_ptr<const test_type*>();
|
const test_type* p2 = value.get_ptr<const test_type*>();
|
||||||
|
@ -2781,14 +2781,14 @@ TEST_CASE("reference access")
|
||||||
// check if references are returned correctly
|
// check if references are returned correctly
|
||||||
test_type& p1 = value.get_ref<test_type&>();
|
test_type& p1 = value.get_ref<test_type&>();
|
||||||
CHECK(&p1 == value.get_ptr<test_type*>());
|
CHECK(&p1 == value.get_ptr<test_type*>());
|
||||||
CHECK(p1 == value.get<test_type>());
|
CHECK(p1 == value.get<test_type>());
|
||||||
|
|
||||||
const test_type& p2 = value.get_ref<const test_type&>();
|
const test_type& p2 = value.get_ref<const test_type&>();
|
||||||
CHECK(&p2 == value.get_ptr<const test_type*>());
|
CHECK(&p2 == value.get_ptr<const test_type*>());
|
||||||
CHECK(p2 == value.get<test_type>());
|
CHECK(p2 == value.get<test_type>());
|
||||||
|
|
||||||
// check if mismatching references throw correctly
|
// check if mismatching references throw correctly
|
||||||
CHECK_NOTHROW(value.get_ref<json::object_t&>());
|
CHECK_NOTHROW(value.get_ref<json::object_t&>());
|
||||||
CHECK_THROWS(value.get_ref<json::array_t&>());
|
CHECK_THROWS(value.get_ref<json::array_t&>());
|
||||||
CHECK_THROWS(value.get_ref<json::string_t&>());
|
CHECK_THROWS(value.get_ref<json::string_t&>());
|
||||||
CHECK_THROWS(value.get_ref<json::boolean_t&>());
|
CHECK_THROWS(value.get_ref<json::boolean_t&>());
|
||||||
|
@ -2796,13 +2796,13 @@ TEST_CASE("reference access")
|
||||||
CHECK_THROWS(value.get_ref<json::number_float_t&>());
|
CHECK_THROWS(value.get_ref<json::number_float_t&>());
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("const reference access to const object_t")
|
SECTION("const reference access to const object_t")
|
||||||
{
|
{
|
||||||
using test_type = json::object_t;
|
using test_type = json::object_t;
|
||||||
const json value = {{"one", 1}, {"two", 2}};
|
const json value = {{"one", 1}, {"two", 2}};
|
||||||
|
|
||||||
// this should not compile
|
// this should not compile
|
||||||
// test_type& p1 = value.get_ref<test_type&>();
|
// test_type& p1 = value.get_ref<test_type&>();
|
||||||
|
|
||||||
// check if references are returned correctly
|
// check if references are returned correctly
|
||||||
const test_type& p2 = value.get_ref<const test_type&>();
|
const test_type& p2 = value.get_ref<const test_type&>();
|
||||||
|
@ -2818,7 +2818,7 @@ TEST_CASE("reference access")
|
||||||
// check if references are returned correctly
|
// check if references are returned correctly
|
||||||
test_type& p1 = value.get_ref<test_type&>();
|
test_type& p1 = value.get_ref<test_type&>();
|
||||||
CHECK(&p1 == value.get_ptr<test_type*>());
|
CHECK(&p1 == value.get_ptr<test_type*>());
|
||||||
CHECK(p1 == value.get<test_type>());
|
CHECK(p1 == value.get<test_type>());
|
||||||
|
|
||||||
const test_type& p2 = value.get_ref<const test_type&>();
|
const test_type& p2 = value.get_ref<const test_type&>();
|
||||||
CHECK(&p2 == value.get_ptr<const test_type*>());
|
CHECK(&p2 == value.get_ptr<const test_type*>());
|
||||||
|
@ -2841,7 +2841,7 @@ TEST_CASE("reference access")
|
||||||
// check if references are returned correctly
|
// check if references are returned correctly
|
||||||
test_type& p1 = value.get_ref<test_type&>();
|
test_type& p1 = value.get_ref<test_type&>();
|
||||||
CHECK(&p1 == value.get_ptr<test_type*>());
|
CHECK(&p1 == value.get_ptr<test_type*>());
|
||||||
CHECK(p1 == value.get<test_type>());
|
CHECK(p1 == value.get<test_type>());
|
||||||
|
|
||||||
const test_type& p2 = value.get_ref<const test_type&>();
|
const test_type& p2 = value.get_ref<const test_type&>();
|
||||||
CHECK(&p2 == value.get_ptr<const test_type*>());
|
CHECK(&p2 == value.get_ptr<const test_type*>());
|
||||||
|
@ -2864,7 +2864,7 @@ TEST_CASE("reference access")
|
||||||
// check if references are returned correctly
|
// check if references are returned correctly
|
||||||
test_type& p1 = value.get_ref<test_type&>();
|
test_type& p1 = value.get_ref<test_type&>();
|
||||||
CHECK(&p1 == value.get_ptr<test_type*>());
|
CHECK(&p1 == value.get_ptr<test_type*>());
|
||||||
CHECK(p1 == value.get<test_type>());
|
CHECK(p1 == value.get<test_type>());
|
||||||
|
|
||||||
const test_type& p2 = value.get_ref<const test_type&>();
|
const test_type& p2 = value.get_ref<const test_type&>();
|
||||||
CHECK(&p2 == value.get_ptr<const test_type*>());
|
CHECK(&p2 == value.get_ptr<const test_type*>());
|
||||||
|
@ -2884,10 +2884,10 @@ TEST_CASE("reference access")
|
||||||
using test_type = json::number_integer_t;
|
using test_type = json::number_integer_t;
|
||||||
json value = 23;
|
json value = 23;
|
||||||
|
|
||||||
// check if references are returned correctly
|
// check if references are returned correctly
|
||||||
test_type& p1 = value.get_ref<test_type&>();
|
test_type& p1 = value.get_ref<test_type&>();
|
||||||
CHECK(&p1 == value.get_ptr<test_type*>());
|
CHECK(&p1 == value.get_ptr<test_type*>());
|
||||||
CHECK(p1 == value.get<test_type>());
|
CHECK(p1 == value.get<test_type>());
|
||||||
|
|
||||||
const test_type& p2 = value.get_ref<const test_type&>();
|
const test_type& p2 = value.get_ref<const test_type&>();
|
||||||
CHECK(&p2 == value.get_ptr<const test_type*>());
|
CHECK(&p2 == value.get_ptr<const test_type*>());
|
||||||
|
@ -2907,10 +2907,10 @@ TEST_CASE("reference access")
|
||||||
using test_type = json::number_float_t;
|
using test_type = json::number_float_t;
|
||||||
json value = 42.23;
|
json value = 42.23;
|
||||||
|
|
||||||
// check if references are returned correctly
|
// check if references are returned correctly
|
||||||
test_type& p1 = value.get_ref<test_type&>();
|
test_type& p1 = value.get_ref<test_type&>();
|
||||||
CHECK(&p1 == value.get_ptr<test_type*>());
|
CHECK(&p1 == value.get_ptr<test_type*>());
|
||||||
CHECK(p1 == value.get<test_type>());
|
CHECK(p1 == value.get<test_type>());
|
||||||
|
|
||||||
const test_type& p2 = value.get_ref<const test_type&>();
|
const test_type& p2 = value.get_ref<const test_type&>();
|
||||||
CHECK(&p2 == value.get_ptr<const test_type*>());
|
CHECK(&p2 == value.get_ptr<const test_type*>());
|
||||||
|
|
Loading…
Reference in a new issue