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.
 | 
			
		||||
- [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.
 | 
			
		||||
- [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.
 | 
			
		||||
- [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.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,13 +13,13 @@ int main()
 | 
			
		|||
 | 
			
		||||
    // print the values
 | 
			
		||||
    std::cout << r1 << ' ' << r2 << '\n';
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    // incompatible type throws exception
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
        auto r3 = value.get_ref<json::number_float_t&>();
 | 
			
		||||
    }
 | 
			
		||||
    catch(std::domain_error& ex)
 | 
			
		||||
    catch (std::domain_error& ex)
 | 
			
		||||
    {
 | 
			
		||||
        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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	/// helper function to implement get_ref without code duplication 
 | 
			
		||||
	/// for const and non-const overloads
 | 
			
		||||
	/// ThisType will be deduced as 'basic_jason' or 'const basic_json'
 | 
			
		||||
	template<typename ReferenceType, typename ThisType>
 | 
			
		||||
    /*!
 | 
			
		||||
    @brief helper function to implement get_ref()
 | 
			
		||||
 | 
			
		||||
    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)
 | 
			
		||||
    {
 | 
			
		||||
		using PointerType = typename std::add_pointer<ReferenceType>::type;
 | 
			
		||||
        // delegate the call to get_ptr<>()
 | 
			
		||||
        using PointerType = typename std::add_pointer<ReferenceType>::type;
 | 
			
		||||
        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:
 | 
			
		||||
| 
						 | 
				
			
			@ -2576,7 +2592,7 @@ class basic_json
 | 
			
		|||
        return get_impl_ptr(static_cast<const PointerType>(nullptr));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	/*!
 | 
			
		||||
    /*!
 | 
			
		||||
    @brief get a reference value (implicit)
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
    state.
 | 
			
		||||
 | 
			
		||||
    @tparam ReferenceType reference type; must be a reference to @ref array_t, @ref
 | 
			
		||||
    object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or @ref
 | 
			
		||||
    number_float_t.
 | 
			
		||||
    @tparam ReferenceType reference type; must be a reference to @ref array_t,
 | 
			
		||||
    @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or
 | 
			
		||||
    @ref number_float_t.
 | 
			
		||||
 | 
			
		||||
    @return reference to the internally stored JSON value if the requested reference
 | 
			
		||||
    type @a ReferenceType fits to the JSON value; throws std::domain_error otherwise
 | 
			
		||||
    @return reference to the internally stored JSON value if the requested
 | 
			
		||||
    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
 | 
			
		||||
    with the stored JSON value
 | 
			
		||||
    @throw std::domain_error in case passed type @a ReferenceType is
 | 
			
		||||
    incompatible with the stored JSON value
 | 
			
		||||
 | 
			
		||||
    @complexity Constant.
 | 
			
		||||
 | 
			
		||||
    @liveexample{The example shows several calls to `get_ref()`.,get_ref}
 | 
			
		||||
 | 
			
		||||
    @since version 1.0.1
 | 
			
		||||
    */
 | 
			
		||||
    template<typename ReferenceType, typename
 | 
			
		||||
             std::enable_if<
 | 
			
		||||
| 
						 | 
				
			
			@ -2603,8 +2624,8 @@ class basic_json
 | 
			
		|||
                 , int>::type = 0>
 | 
			
		||||
    ReferenceType get_ref()
 | 
			
		||||
    {
 | 
			
		||||
		// delegate call to get_ref_impl
 | 
			
		||||
		return get_ref_impl<ReferenceType>(*this);
 | 
			
		||||
        // delegate call to get_ref_impl
 | 
			
		||||
        return get_ref_impl<ReferenceType>(*this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*!
 | 
			
		||||
| 
						 | 
				
			
			@ -2614,12 +2635,12 @@ class basic_json
 | 
			
		|||
    template<typename ReferenceType, typename
 | 
			
		||||
             std::enable_if<
 | 
			
		||||
                 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>
 | 
			
		||||
    ReferenceType get_ref() const
 | 
			
		||||
    {
 | 
			
		||||
		// delegate call to get_ref_impl
 | 
			
		||||
		return get_ref_impl<ReferenceType>(*this);
 | 
			
		||||
        // delegate call to get_ref_impl
 | 
			
		||||
        return get_ref_impl<ReferenceType>(*this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*!
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2416,17 +2416,33 @@ class basic_json
 | 
			
		|||
        return is_number_float() ? &m_value.number_float : nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	/// helper function to implement get_ref without code duplication 
 | 
			
		||||
	/// for const and non-const overloads
 | 
			
		||||
	/// ThisType will be deduced as 'basic_jason' or 'const basic_json'
 | 
			
		||||
	template<typename ReferenceType, typename ThisType>
 | 
			
		||||
    /*!
 | 
			
		||||
    @brief helper function to implement get_ref()
 | 
			
		||||
 | 
			
		||||
    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)
 | 
			
		||||
    {
 | 
			
		||||
		using PointerType = typename std::add_pointer<ReferenceType>::type;
 | 
			
		||||
        // delegate the call to get_ptr<>()
 | 
			
		||||
        using PointerType = typename std::add_pointer<ReferenceType>::type;
 | 
			
		||||
        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:
 | 
			
		||||
| 
						 | 
				
			
			@ -2576,7 +2592,7 @@ class basic_json
 | 
			
		|||
        return get_impl_ptr(static_cast<const PointerType>(nullptr));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	/*!
 | 
			
		||||
    /*!
 | 
			
		||||
    @brief get a reference value (implicit)
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
    state.
 | 
			
		||||
 | 
			
		||||
    @tparam ReferenceType reference type; must be a reference to @ref array_t, @ref
 | 
			
		||||
    object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or @ref
 | 
			
		||||
    number_float_t.
 | 
			
		||||
    @tparam ReferenceType reference type; must be a reference to @ref array_t,
 | 
			
		||||
    @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or
 | 
			
		||||
    @ref number_float_t.
 | 
			
		||||
 | 
			
		||||
    @return reference to the internally stored JSON value if the requested reference
 | 
			
		||||
    type @a ReferenceType fits to the JSON value; throws std::domain_error otherwise
 | 
			
		||||
    @return reference to the internally stored JSON value if the requested
 | 
			
		||||
    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
 | 
			
		||||
    with the stored JSON value
 | 
			
		||||
    @throw std::domain_error in case passed type @a ReferenceType is
 | 
			
		||||
    incompatible with the stored JSON value
 | 
			
		||||
 | 
			
		||||
    @complexity Constant.
 | 
			
		||||
 | 
			
		||||
    @liveexample{The example shows several calls to `get_ref()`.,get_ref}
 | 
			
		||||
 | 
			
		||||
    @since version 1.0.1
 | 
			
		||||
    */
 | 
			
		||||
    template<typename ReferenceType, typename
 | 
			
		||||
             std::enable_if<
 | 
			
		||||
| 
						 | 
				
			
			@ -2603,8 +2624,8 @@ class basic_json
 | 
			
		|||
                 , int>::type = 0>
 | 
			
		||||
    ReferenceType get_ref()
 | 
			
		||||
    {
 | 
			
		||||
		// delegate call to get_ref_impl
 | 
			
		||||
		return get_ref_impl<ReferenceType>(*this);
 | 
			
		||||
        // delegate call to get_ref_impl
 | 
			
		||||
        return get_ref_impl<ReferenceType>(*this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*!
 | 
			
		||||
| 
						 | 
				
			
			@ -2614,12 +2635,12 @@ class basic_json
 | 
			
		|||
    template<typename ReferenceType, typename
 | 
			
		||||
             std::enable_if<
 | 
			
		||||
                 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>
 | 
			
		||||
    ReferenceType get_ref() const
 | 
			
		||||
    {
 | 
			
		||||
		// delegate call to get_ref_impl
 | 
			
		||||
		return get_ref_impl<ReferenceType>(*this);
 | 
			
		||||
        // delegate call to get_ref_impl
 | 
			
		||||
        return get_ref_impl<ReferenceType>(*this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*!
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2604,13 +2604,13 @@ TEST_CASE("pointer access")
 | 
			
		|||
        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;
 | 
			
		||||
        const json value = {{"one", 1}, {"two", 2}};
 | 
			
		||||
 | 
			
		||||
		// this should not compile
 | 
			
		||||
		// test_type* p1 = value.get_ptr<test_type*>();
 | 
			
		||||
        // this should not compile
 | 
			
		||||
        // test_type* p1 = value.get_ptr<test_type*>();
 | 
			
		||||
 | 
			
		||||
        // check if pointers are returned correctly
 | 
			
		||||
        const test_type* p2 = value.get_ptr<const test_type*>();
 | 
			
		||||
| 
						 | 
				
			
			@ -2781,14 +2781,14 @@ TEST_CASE("reference access")
 | 
			
		|||
        // check if references are returned correctly
 | 
			
		||||
        test_type& p1 = value.get_ref<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&>();
 | 
			
		||||
        CHECK(&p2 == value.get_ptr<const test_type*>());
 | 
			
		||||
        CHECK(p2 == value.get<test_type>());
 | 
			
		||||
 | 
			
		||||
        // 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::string_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&>());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	SECTION("const reference access to const object_t")
 | 
			
		||||
    SECTION("const reference access to const object_t")
 | 
			
		||||
    {
 | 
			
		||||
        using test_type = json::object_t;
 | 
			
		||||
        const json value = {{"one", 1}, {"two", 2}};
 | 
			
		||||
 | 
			
		||||
		// this should not compile
 | 
			
		||||
		// test_type& p1 = value.get_ref<test_type&>();
 | 
			
		||||
        // this should not compile
 | 
			
		||||
        // test_type& p1 = value.get_ref<test_type&>();
 | 
			
		||||
 | 
			
		||||
        // check if references are returned correctly
 | 
			
		||||
        const test_type& p2 = value.get_ref<const test_type&>();
 | 
			
		||||
| 
						 | 
				
			
			@ -2818,7 +2818,7 @@ TEST_CASE("reference access")
 | 
			
		|||
        // check if references are returned correctly
 | 
			
		||||
        test_type& p1 = value.get_ref<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&>();
 | 
			
		||||
        CHECK(&p2 == value.get_ptr<const test_type*>());
 | 
			
		||||
| 
						 | 
				
			
			@ -2841,7 +2841,7 @@ TEST_CASE("reference access")
 | 
			
		|||
        // check if references are returned correctly
 | 
			
		||||
        test_type& p1 = value.get_ref<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&>();
 | 
			
		||||
        CHECK(&p2 == value.get_ptr<const test_type*>());
 | 
			
		||||
| 
						 | 
				
			
			@ -2864,7 +2864,7 @@ TEST_CASE("reference access")
 | 
			
		|||
        // check if references are returned correctly
 | 
			
		||||
        test_type& p1 = value.get_ref<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&>();
 | 
			
		||||
        CHECK(&p2 == value.get_ptr<const test_type*>());
 | 
			
		||||
| 
						 | 
				
			
			@ -2884,10 +2884,10 @@ TEST_CASE("reference access")
 | 
			
		|||
        using test_type = json::number_integer_t;
 | 
			
		||||
        json value = 23;
 | 
			
		||||
 | 
			
		||||
		// check if references are returned correctly
 | 
			
		||||
        // check if references are returned correctly
 | 
			
		||||
        test_type& p1 = value.get_ref<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&>();
 | 
			
		||||
        CHECK(&p2 == value.get_ptr<const test_type*>());
 | 
			
		||||
| 
						 | 
				
			
			@ -2907,10 +2907,10 @@ TEST_CASE("reference access")
 | 
			
		|||
        using test_type = json::number_float_t;
 | 
			
		||||
        json value = 42.23;
 | 
			
		||||
 | 
			
		||||
		// check if references are returned correctly
 | 
			
		||||
        // check if references are returned correctly
 | 
			
		||||
        test_type& p1 = value.get_ref<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&>();
 | 
			
		||||
        CHECK(&p2 == value.get_ptr<const test_type*>());
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue