Merge upstream commits and resolve conflicts
This commit is contained in:
commit
421affd06e
5 changed files with 276 additions and 81 deletions
|
@ -62,6 +62,7 @@ Please understand that I cannot accept pull requests changing only file `src/jso
|
|||
- The C++11 support varies between different **compilers** and versions. Please note the [list of supported compilers](https://github.com/nlohmann/json/blob/master/README.md#supported-compilers). Some compilers like GCC 4.8 (and earlier), Clang 3.3 (and earlier), or Microsoft Visual Studio 13.0 and earlier are known not to work due to missing or incomplete C++11 support. Please refrain from proposing changes that work around these compiler's limitations with `#ifdef`s or other means.
|
||||
- Specifically, I am aware of compilation problems with **Microsoft Visual Studio** (there even is an [issue label](https://github.com/nlohmann/json/issues?utf8=✓&q=label%3A%22visual+studio%22+) for these kind of bugs). I understand that even in 2016, complete C++11 support isn't there yet. But please also understand that I do not want to drop features or uglify the code just to make Microsoft's sub-standard compiler happy. The past has shown that there are ways to express the functionality such that the code compiles with the most recent MSVC - unfortunately, this is not the main objective of the project.
|
||||
- Please refrain from proposing changes that would **break [JSON](http://json.org) conformance**. If you propose a conformant extension of JSON to be supported by the library, please motivate this extension.
|
||||
- Please do not open pull requests that address **multiple issues**.
|
||||
|
||||
## Wanted
|
||||
|
||||
|
|
|
@ -388,6 +388,7 @@ I deeply appreciate the help of the following people.
|
|||
- [406345](https://github.com/406345) fixed two small warnings.
|
||||
- [Glen Fernandes](https://github.com/glenfe) noted a potential portability problem in the `has_mapped_type` function.
|
||||
- [Corbin Hughes](https://github.com/nibroc) fixed some typos in the contribution guidelines.
|
||||
- [twelsby](https://github.com/twelsby) fixed the array subscript operator and an issue that failed the MSVC build.
|
||||
|
||||
Thanks a lot for helping out!
|
||||
|
||||
|
@ -404,7 +405,7 @@ $ make
|
|||
$ ./json_unit "*"
|
||||
|
||||
===============================================================================
|
||||
All tests passed (3343239 assertions in 28 test cases)
|
||||
All tests passed (3343318 assertions in 29 test cases)
|
||||
```
|
||||
|
||||
For more information, have a look at the file [.travis.yml](https://github.com/nlohmann/json/blob/master/.travis.yml).
|
||||
|
|
142
src/json.hpp
142
src/json.hpp
|
@ -43,7 +43,9 @@ Class @ref nlohmann::basic_json is a good entry point for the documentation.
|
|||
#include <cassert>
|
||||
#include <ciso646>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <iomanip>
|
||||
|
@ -53,6 +55,7 @@ Class @ref nlohmann::basic_json is a good entry point for the documentation.
|
|||
#include <map>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
@ -65,6 +68,12 @@ Class @ref nlohmann::basic_json is a good entry point for the documentation.
|
|||
#endif
|
||||
#endif
|
||||
|
||||
// disable float-equal warnings on GCC/clang
|
||||
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||
#endif
|
||||
|
||||
// enable ssize_t for MSVC
|
||||
#ifdef _MSC_VER
|
||||
#include <basetsd.h>
|
||||
|
@ -100,12 +109,6 @@ struct has_mapped_type
|
|||
static constexpr bool value = sizeof(test<T>(0)) == 1;
|
||||
};
|
||||
|
||||
/// "equality" comparison for floating point numbers
|
||||
template<typename T>
|
||||
static bool approx(const T a, const T b)
|
||||
{
|
||||
return not (a > b or a < b);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -2671,14 +2674,14 @@ class basic_json
|
|||
|
||||
@since version 1.0.0
|
||||
*/
|
||||
template<typename ValueType, typename
|
||||
std::enable_if<
|
||||
template < typename ValueType, typename
|
||||
std::enable_if <
|
||||
not std::is_pointer<ValueType>::value
|
||||
and not std::is_same<ValueType, typename string_t::value_type>::value
|
||||
#ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015
|
||||
and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
|
||||
#endif
|
||||
, int>::type = 0>
|
||||
, int >::type = 0 >
|
||||
operator ValueType() const
|
||||
{
|
||||
// delegate the call to get<>() const
|
||||
|
@ -3062,8 +3065,6 @@ class basic_json
|
|||
the object and filled with a `null` value to make `key` a valid reference.
|
||||
In case the value was `null` before, it is converted to an object.
|
||||
|
||||
@note This function is required for compatibility reasons with Clang.
|
||||
|
||||
@param[in] key key of the element to access
|
||||
|
||||
@return reference to the element at key @a key
|
||||
|
@ -3083,25 +3084,9 @@ class basic_json
|
|||
@since version 1.0.0
|
||||
*/
|
||||
template<typename T, std::size_t n>
|
||||
reference operator[](const T (&key)[n])
|
||||
reference operator[](T * (&key)[n])
|
||||
{
|
||||
// implicitly convert null to object
|
||||
if (is_null())
|
||||
{
|
||||
m_type = value_t::object;
|
||||
m_value = value_t::object;
|
||||
}
|
||||
|
||||
// at only works for objects
|
||||
if (is_object())
|
||||
{
|
||||
assert(m_value.object != nullptr);
|
||||
return m_value.object->operator[](key);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::domain_error("cannot use operator[] with " + type_name());
|
||||
}
|
||||
return operator[](static_cast<const T>(key));
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -3134,7 +3119,89 @@ class basic_json
|
|||
@since version 1.0.0
|
||||
*/
|
||||
template<typename T, std::size_t n>
|
||||
const_reference operator[](const T (&key)[n]) const
|
||||
const_reference operator[](T * (&key)[n]) const
|
||||
{
|
||||
return operator[](static_cast<const T>(key));
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief access specified object element
|
||||
|
||||
Returns a reference to the element at with specified key @a key.
|
||||
|
||||
@note If @a key is not found in the object, then it is silently added to
|
||||
the object and filled with a `null` value to make `key` a valid reference.
|
||||
In case the value was `null` before, it is converted to an object.
|
||||
|
||||
@param[in] key key of the element to access
|
||||
|
||||
@return reference to the element at key @a key
|
||||
|
||||
@throw std::domain_error if JSON is not an object or null; example:
|
||||
`"cannot use operator[] with null"`
|
||||
|
||||
@complexity Logarithmic in the size of the container.
|
||||
|
||||
@liveexample{The example below shows how object elements can be read and
|
||||
written using the [] operator.,operatorarray__key_type}
|
||||
|
||||
@sa @ref at(const typename object_t::key_type&) for access by reference
|
||||
with range checking
|
||||
@sa @ref value() for access by value with a default value
|
||||
|
||||
@since version 1.0.1
|
||||
*/
|
||||
template<typename T>
|
||||
reference operator[](T* key)
|
||||
{
|
||||
// implicitly convert null to object
|
||||
if (is_null())
|
||||
{
|
||||
m_type = value_t::object;
|
||||
m_value = value_t::object;
|
||||
}
|
||||
|
||||
// at only works for objects
|
||||
if (is_object())
|
||||
{
|
||||
assert(m_value.object != nullptr);
|
||||
return m_value.object->operator[](key);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::domain_error("cannot use operator[] with " + type_name());
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief read-only access specified object element
|
||||
|
||||
Returns a const reference to the element at with specified key @a key. No
|
||||
bounds checking is performed.
|
||||
|
||||
@warning If the element with key @a key does not exist, the behavior is
|
||||
undefined.
|
||||
|
||||
@param[in] key key of the element to access
|
||||
|
||||
@return const reference to the element at key @a key
|
||||
|
||||
@throw std::domain_error if JSON is not an object; example: `"cannot use
|
||||
operator[] with null"`
|
||||
|
||||
@complexity Logarithmic in the size of the container.
|
||||
|
||||
@liveexample{The example below shows how object elements can be read using
|
||||
the [] operator.,operatorarray__key_type_const}
|
||||
|
||||
@sa @ref at(const typename object_t::key_type&) for access by reference
|
||||
with range checking
|
||||
@sa @ref value() for access by value with a default value
|
||||
|
||||
@since version 1.0.1
|
||||
*/
|
||||
template<typename T>
|
||||
const_reference operator[](T* key) const
|
||||
{
|
||||
// at only works for objects
|
||||
if (is_object())
|
||||
|
@ -4785,7 +4852,7 @@ class basic_json
|
|||
}
|
||||
case value_t::number_float:
|
||||
{
|
||||
return approx(lhs.m_value.number_float, rhs.m_value.number_float);
|
||||
return lhs.m_value.number_float == rhs.m_value.number_float;
|
||||
}
|
||||
default:
|
||||
{
|
||||
|
@ -4795,13 +4862,11 @@ class basic_json
|
|||
}
|
||||
else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
|
||||
{
|
||||
return approx(static_cast<number_float_t>(lhs.m_value.number_integer),
|
||||
rhs.m_value.number_float);
|
||||
return static_cast<number_float_t>(lhs.m_value.number_integer == rhs.m_value.number_float);
|
||||
}
|
||||
else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
|
||||
{
|
||||
return approx(lhs.m_value.number_float,
|
||||
static_cast<number_float_t>(rhs.m_value.number_integer));
|
||||
return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -7622,7 +7687,7 @@ basic_json_parser_64:
|
|||
|
||||
// check if conversion loses precision (special case -0.0 always loses precision)
|
||||
const auto int_val = static_cast<number_integer_t>(result.m_value.number_float);
|
||||
if (approx(result.m_value.number_float, static_cast<number_float_t>(int_val)) &&
|
||||
if (result.m_value.number_float == static_cast<number_float_t>(int_val) &&
|
||||
result.m_value.number_integer != json_value(-0.0f).number_integer)
|
||||
{
|
||||
// we would not lose precision -> return int
|
||||
|
@ -7767,4 +7832,9 @@ inline nlohmann::json operator "" _json(const char* s, std::size_t)
|
|||
return nlohmann::json::parse(reinterpret_cast<const nlohmann::json::string_t::value_type*>(s));
|
||||
}
|
||||
|
||||
// restore GCC/clang diagnostic settings
|
||||
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -43,7 +43,9 @@ Class @ref nlohmann::basic_json is a good entry point for the documentation.
|
|||
#include <cassert>
|
||||
#include <ciso646>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <iomanip>
|
||||
|
@ -53,6 +55,7 @@ Class @ref nlohmann::basic_json is a good entry point for the documentation.
|
|||
#include <map>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
@ -65,6 +68,12 @@ Class @ref nlohmann::basic_json is a good entry point for the documentation.
|
|||
#endif
|
||||
#endif
|
||||
|
||||
// disable float-equal warnings on GCC/clang
|
||||
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||
#endif
|
||||
|
||||
// enable ssize_t for MSVC
|
||||
#ifdef _MSC_VER
|
||||
#include <basetsd.h>
|
||||
|
@ -100,12 +109,6 @@ struct has_mapped_type
|
|||
static constexpr bool value = sizeof(test<T>(0)) == 1;
|
||||
};
|
||||
|
||||
/// "equality" comparison for floating point numbers
|
||||
template<typename T>
|
||||
static bool approx(const T a, const T b)
|
||||
{
|
||||
return not (a > b or a < b);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -2671,14 +2674,14 @@ class basic_json
|
|||
|
||||
@since version 1.0.0
|
||||
*/
|
||||
template<typename ValueType, typename
|
||||
std::enable_if<
|
||||
template < typename ValueType, typename
|
||||
std::enable_if <
|
||||
not std::is_pointer<ValueType>::value
|
||||
and not std::is_same<ValueType, typename string_t::value_type>::value
|
||||
#ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015
|
||||
and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
|
||||
#endif
|
||||
, int>::type = 0>
|
||||
, int >::type = 0 >
|
||||
operator ValueType() const
|
||||
{
|
||||
// delegate the call to get<>() const
|
||||
|
@ -3062,8 +3065,6 @@ class basic_json
|
|||
the object and filled with a `null` value to make `key` a valid reference.
|
||||
In case the value was `null` before, it is converted to an object.
|
||||
|
||||
@note This function is required for compatibility reasons with Clang.
|
||||
|
||||
@param[in] key key of the element to access
|
||||
|
||||
@return reference to the element at key @a key
|
||||
|
@ -3083,25 +3084,9 @@ class basic_json
|
|||
@since version 1.0.0
|
||||
*/
|
||||
template<typename T, std::size_t n>
|
||||
reference operator[](const T (&key)[n])
|
||||
reference operator[](T * (&key)[n])
|
||||
{
|
||||
// implicitly convert null to object
|
||||
if (is_null())
|
||||
{
|
||||
m_type = value_t::object;
|
||||
m_value = value_t::object;
|
||||
}
|
||||
|
||||
// at only works for objects
|
||||
if (is_object())
|
||||
{
|
||||
assert(m_value.object != nullptr);
|
||||
return m_value.object->operator[](key);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::domain_error("cannot use operator[] with " + type_name());
|
||||
}
|
||||
return operator[](static_cast<const T>(key));
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -3134,7 +3119,89 @@ class basic_json
|
|||
@since version 1.0.0
|
||||
*/
|
||||
template<typename T, std::size_t n>
|
||||
const_reference operator[](const T (&key)[n]) const
|
||||
const_reference operator[](T * (&key)[n]) const
|
||||
{
|
||||
return operator[](static_cast<const T>(key));
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief access specified object element
|
||||
|
||||
Returns a reference to the element at with specified key @a key.
|
||||
|
||||
@note If @a key is not found in the object, then it is silently added to
|
||||
the object and filled with a `null` value to make `key` a valid reference.
|
||||
In case the value was `null` before, it is converted to an object.
|
||||
|
||||
@param[in] key key of the element to access
|
||||
|
||||
@return reference to the element at key @a key
|
||||
|
||||
@throw std::domain_error if JSON is not an object or null; example:
|
||||
`"cannot use operator[] with null"`
|
||||
|
||||
@complexity Logarithmic in the size of the container.
|
||||
|
||||
@liveexample{The example below shows how object elements can be read and
|
||||
written using the [] operator.,operatorarray__key_type}
|
||||
|
||||
@sa @ref at(const typename object_t::key_type&) for access by reference
|
||||
with range checking
|
||||
@sa @ref value() for access by value with a default value
|
||||
|
||||
@since version 1.0.1
|
||||
*/
|
||||
template<typename T>
|
||||
reference operator[](T* key)
|
||||
{
|
||||
// implicitly convert null to object
|
||||
if (is_null())
|
||||
{
|
||||
m_type = value_t::object;
|
||||
m_value = value_t::object;
|
||||
}
|
||||
|
||||
// at only works for objects
|
||||
if (is_object())
|
||||
{
|
||||
assert(m_value.object != nullptr);
|
||||
return m_value.object->operator[](key);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::domain_error("cannot use operator[] with " + type_name());
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief read-only access specified object element
|
||||
|
||||
Returns a const reference to the element at with specified key @a key. No
|
||||
bounds checking is performed.
|
||||
|
||||
@warning If the element with key @a key does not exist, the behavior is
|
||||
undefined.
|
||||
|
||||
@param[in] key key of the element to access
|
||||
|
||||
@return const reference to the element at key @a key
|
||||
|
||||
@throw std::domain_error if JSON is not an object; example: `"cannot use
|
||||
operator[] with null"`
|
||||
|
||||
@complexity Logarithmic in the size of the container.
|
||||
|
||||
@liveexample{The example below shows how object elements can be read using
|
||||
the [] operator.,operatorarray__key_type_const}
|
||||
|
||||
@sa @ref at(const typename object_t::key_type&) for access by reference
|
||||
with range checking
|
||||
@sa @ref value() for access by value with a default value
|
||||
|
||||
@since version 1.0.1
|
||||
*/
|
||||
template<typename T>
|
||||
const_reference operator[](T* key) const
|
||||
{
|
||||
// at only works for objects
|
||||
if (is_object())
|
||||
|
@ -4785,7 +4852,7 @@ class basic_json
|
|||
}
|
||||
case value_t::number_float:
|
||||
{
|
||||
return approx(lhs.m_value.number_float, rhs.m_value.number_float);
|
||||
return lhs.m_value.number_float == rhs.m_value.number_float;
|
||||
}
|
||||
default:
|
||||
{
|
||||
|
@ -4795,13 +4862,11 @@ class basic_json
|
|||
}
|
||||
else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
|
||||
{
|
||||
return approx(static_cast<number_float_t>(lhs.m_value.number_integer),
|
||||
rhs.m_value.number_float);
|
||||
return static_cast<number_float_t>(lhs.m_value.number_integer == rhs.m_value.number_float);
|
||||
}
|
||||
else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
|
||||
{
|
||||
return approx(lhs.m_value.number_float,
|
||||
static_cast<number_float_t>(rhs.m_value.number_integer));
|
||||
return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -7304,7 +7369,7 @@ class basic_json
|
|||
|
||||
// check if conversion loses precision (special case -0.0 always loses precision)
|
||||
const auto int_val = static_cast<number_integer_t>(result.m_value.number_float);
|
||||
if (approx(result.m_value.number_float, static_cast<number_float_t>(int_val)) &&
|
||||
if (result.m_value.number_float == static_cast<number_float_t>(int_val) &&
|
||||
result.m_value.number_integer != json_value(-0.0f).number_integer)
|
||||
{
|
||||
// we would not lose precision -> return int
|
||||
|
@ -7449,4 +7514,9 @@ inline nlohmann::json operator "" _json(const char* s, std::size_t)
|
|||
return nlohmann::json::parse(reinterpret_cast<const nlohmann::json::string_t::value_type*>(s));
|
||||
}
|
||||
|
||||
// restore GCC/clang diagnostic settings
|
||||
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -25,6 +25,11 @@
|
|||
#include "json.hpp"
|
||||
using nlohmann::json;
|
||||
|
||||
// disable float-equal warnings on GCC/clang
|
||||
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||
#endif
|
||||
|
||||
TEST_CASE("constructors")
|
||||
{
|
||||
SECTION("create an empty value with a given type")
|
||||
|
@ -11501,11 +11506,59 @@ TEST_CASE("regression tests")
|
|||
CHECK(s2 == "value");
|
||||
}
|
||||
|
||||
SECTION("character following a surrogate pair is skipped")
|
||||
SECTION("issue #146 - character following a surrogate pair is skipped")
|
||||
{
|
||||
CHECK(json::parse("\"\\ud80c\\udc60abc\"").get<json::string_t>() == u8"\U00013060abc");
|
||||
}
|
||||
|
||||
SECTION("issue #171 - Cannot index by key of type static constexpr const char*")
|
||||
{
|
||||
json j;
|
||||
|
||||
// Non-const access with key as "char []"
|
||||
char array_key[] = "Key1";
|
||||
CHECK_NOTHROW(j[array_key] = 1);
|
||||
CHECK(j[array_key] == json(1));
|
||||
|
||||
// Non-const access with key as "const char[]"
|
||||
const char const_array_key[] = "Key2";
|
||||
CHECK_NOTHROW(j[const_array_key] = 2);
|
||||
CHECK(j[const_array_key] == json(2));
|
||||
|
||||
// Non-const access with key as "char *"
|
||||
char _ptr_key[] = "Key3";
|
||||
char* ptr_key = &_ptr_key[0];
|
||||
CHECK_NOTHROW(j[ptr_key] = 3);
|
||||
CHECK(j[ptr_key] == json(3));
|
||||
|
||||
// Non-const access with key as "const char *"
|
||||
const char* const_ptr_key = "Key4";
|
||||
CHECK_NOTHROW(j[const_ptr_key] = 4);
|
||||
CHECK(j[const_ptr_key] == json(4));
|
||||
|
||||
// Non-const access with key as "static constexpr const char *"
|
||||
static constexpr const char* constexpr_ptr_key = "Key5";
|
||||
CHECK_NOTHROW(j[constexpr_ptr_key] = 5);
|
||||
CHECK(j[constexpr_ptr_key] == json(5));
|
||||
|
||||
const json j_const = j;
|
||||
|
||||
// Const access with key as "char []"
|
||||
CHECK(j_const[array_key] == json(1));
|
||||
|
||||
// Const access with key as "const char[]"
|
||||
CHECK(j_const[const_array_key] == json(2));
|
||||
|
||||
//Const access with key as "char *"
|
||||
CHECK(j_const[ptr_key] == json(3));
|
||||
|
||||
// Const access with key as "const char *"
|
||||
CHECK(j_const[const_ptr_key] == json(4));
|
||||
|
||||
// Const access with key as "static constexpr const char *"
|
||||
CHECK(j_const[constexpr_ptr_key] == json(5));
|
||||
}
|
||||
|
||||
SECTION("issue #186 miloyip/nativejson-benchmark: floating-point parsing")
|
||||
{
|
||||
json j;
|
||||
|
@ -11520,7 +11573,7 @@ TEST_CASE("regression tests")
|
|||
CHECK(j.get<double>() == 0.99999999999999989);
|
||||
|
||||
// Test fails under GCC/clang due to strtod() error (may originate in libstdc++
|
||||
// but seems to have been fixed in the most current versions)
|
||||
// but seems to have been fixed in the most current versions - just not on Travis)
|
||||
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
|
||||
j = json::parse("1.00000000000000011102230246251565404236316680908203126");
|
||||
CHECK(j.get<double>() == 1.00000000000000022);
|
||||
|
|
Loading…
Reference in a new issue