diff --git a/.travis.yml b/.travis.yml index c3cba69e..dcf7b6a2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -78,13 +78,13 @@ matrix: env: - COMPILER=g++-4.9 - SPECIAL=no_exceptions - - TEST_PATTERN=-e \"*\" addons: apt: sources: ['ubuntu-toolchain-r-test'] packages: [g++-4.9, cppcheck] - before_script: - - CPPFLAGS="-DJSON_NOEXCEPTION" make + after_success: + - make clean + - CPPFLAGS="-DJSON_NOEXCEPTION" make check TEST_PATTERN="-e \"*\"" # Coveralls (http://gronlier.fr/blog/2015/01/adding-code-coverage-to-your-c-project/) diff --git a/README.md b/README.md index 94120db6..2a896210 100644 --- a/README.md +++ b/README.md @@ -828,7 +828,7 @@ I deeply appreciate the help of the following people. - [rswanson-ihi](https://github.com/rswanson-ihi) noted a typo in the README. - [Mihai Stan](https://github.com/stanmihai4) fixed a bug in the comparison with `nullptr`s. - [Tushar Maheshwari](https://github.com/tusharpm) added [cotire](https://github.com/sakra/cotire) support to speed up the compilation. -- [TedLyngmo](https://github.com/TedLyngmo) noted a typo in the README. +- [TedLyngmo](https://github.com/TedLyngmo) noted a typo in the README and fixed some `-Weffc++` warnings. Thanks a lot for helping out! Please [let me know](mailto:mail@nlohmann.me) if I forgot someone. diff --git a/src/json.hpp b/src/json.hpp index 5a3e6c3a..605d6aa5 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -81,7 +81,7 @@ SOFTWARE. #endif // allow to disable exceptions -#if not defined(JSON_NOEXCEPTION) || defined(__EXCEPTIONS) +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && not defined(JSON_NOEXCEPTION) #define JSON_THROW(exception) throw exception #define JSON_TRY try #define JSON_CATCH(exception) catch(exception) @@ -529,6 +529,19 @@ struct external_constructor j.m_value.array = j.template create(begin(arr), end(arr)); j.assert_invariant(); } + + template + static void construct(BasicJsonType& j, const std::vector& arr) + { + j.m_type = value_t::array; + j.m_value = value_t::array; + j.m_value.array->reserve(arr.size()); + for (bool x : arr) + { + j.m_value.array->push_back(x); + } + j.assert_invariant(); + } }; template<> @@ -767,6 +780,12 @@ void to_json(BasicJsonType& j, UnscopedEnumType e) noexcept external_constructor::construct(j, e); } +template +void to_json(BasicJsonType& j, const std::vector& e) +{ + external_constructor::construct(j, e); +} + template < typename BasicJsonType, typename CompatibleArrayType, enable_if_t < @@ -6392,6 +6411,10 @@ class basic_json */ class serializer { + private: + serializer(const serializer&) = delete; + serializer& operator=(const serializer&) = delete; + public: /*! @param[in] s output stream to serialize to @@ -13427,6 +13450,22 @@ struct hash return h(j.dump()); } }; + +/// specialization for std::less +template <> +struct less<::nlohmann::detail::value_t> +{ + /*! + @brief compare two value_t enum values + @since version 3.0.0 + */ + bool operator()(nlohmann::detail::value_t lhs, + nlohmann::detail::value_t rhs) const noexcept + { + return nlohmann::detail::operator<(lhs, rhs); + } +}; + } // namespace std /*! diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 289e3f10..2bd2fd76 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -81,7 +81,7 @@ SOFTWARE. #endif // allow to disable exceptions -#if not defined(JSON_NOEXCEPTION) || defined(__EXCEPTIONS) +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && not defined(JSON_NOEXCEPTION) #define JSON_THROW(exception) throw exception #define JSON_TRY try #define JSON_CATCH(exception) catch(exception) @@ -529,6 +529,19 @@ struct external_constructor j.m_value.array = j.template create(begin(arr), end(arr)); j.assert_invariant(); } + + template + static void construct(BasicJsonType& j, const std::vector& arr) + { + j.m_type = value_t::array; + j.m_value = value_t::array; + j.m_value.array->reserve(arr.size()); + for (bool x : arr) + { + j.m_value.array->push_back(x); + } + j.assert_invariant(); + } }; template<> @@ -767,6 +780,12 @@ void to_json(BasicJsonType& j, UnscopedEnumType e) noexcept external_constructor::construct(j, e); } +template +void to_json(BasicJsonType& j, const std::vector& e) +{ + external_constructor::construct(j, e); +} + template < typename BasicJsonType, typename CompatibleArrayType, enable_if_t < @@ -6392,6 +6411,10 @@ class basic_json */ class serializer { + private: + serializer(const serializer&) = delete; + serializer& operator=(const serializer&) = delete; + public: /*! @param[in] s output stream to serialize to @@ -12460,6 +12483,22 @@ struct hash return h(j.dump()); } }; + +/// specialization for std::less +template <> +struct less<::nlohmann::detail::value_t> +{ + /*! + @brief compare two value_t enum values + @since version 3.0.0 + */ + bool operator()(nlohmann::detail::value_t lhs, + nlohmann::detail::value_t rhs) const noexcept + { + return nlohmann::detail::operator<(lhs, rhs); + } +}; + } // namespace std /*! diff --git a/test/src/unit-modifiers.cpp b/test/src/unit-modifiers.cpp index ad055420..0c332111 100644 --- a/test/src/unit-modifiers.cpp +++ b/test/src/unit-modifiers.cpp @@ -585,10 +585,11 @@ TEST_CASE("modifiers") SECTION("insert nothing (count = 0)") { - auto pos = j_array.end(); auto it = j_array.insert(j_array.end(), 0, 5); CHECK(j_array.size() == 4); - CHECK(it == pos); + // the returned iterator points to the first inserted element; + // there were 4 elements, so it should point to the 5th + CHECK(it == j_array.begin() + 4); CHECK(j_array == json({1, 2, 3, 4})); } } diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index 324ab769..28666169 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -833,4 +833,20 @@ TEST_CASE("regression tests") std::string s2 = j2.dump(); CHECK(s1 == s2); } + + SECTION("issue #486 - json::value_t can't be a map's key type in VC++ 2015") + { + // the code below must compile with MSVC + std::map jsonTypes ; + jsonTypes[json::value_t::array] = "array"; + } + + SECTION("issue #494 - conversion from vector to json fails to build") + { + std::vector boolVector = {false, true, false, false}; + json j; + j["bool_vector"] = boolVector; + + CHECK(j["bool_vector"].dump() == "[false,true,false,false]"); + } } diff --git a/test/src/unit-udt.cpp b/test/src/unit-udt.cpp index a8103082..6aa469fe 100644 --- a/test/src/unit-udt.cpp +++ b/test/src/unit-udt.cpp @@ -49,16 +49,19 @@ enum class country struct age { int m_val; + age(int rhs = 0) : m_val(rhs) {} }; struct name { std::string m_val; + name(const std::string rhs = "") : m_val(rhs) {} }; struct address { std::string m_val; + address(const std::string rhs = "") : m_val(rhs) {} }; struct person @@ -66,18 +69,24 @@ struct person age m_age; name m_name; country m_country; + person() : m_age(), m_name(), m_country() {} + person(const age& a, const name& n, const country& c) : m_age(a), m_name(n), m_country(c) {} }; struct contact { person m_person; address m_address; + contact() : m_person(), m_address() {} + contact(const person& p, const address& a) : m_person(p), m_address(a) {} }; struct contact_book { name m_book_name; std::vector m_contacts; + contact_book() : m_book_name(), m_contacts() {} + contact_book(const name& n, const std::vector& c) : m_book_name(n), m_contacts(c) {} }; } @@ -319,6 +328,8 @@ namespace udt struct legacy_type { std::string number; + legacy_type() : number() {} + legacy_type(const std::string& n) : number(n) {} }; } @@ -593,6 +604,8 @@ struct small_pod struct non_pod { std::string s; + non_pod() : s() {} + non_pod(const std::string& S) : s(S) {} }; template