From 1beec85453448a7186a01a1bb16848d90afe6908 Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Sun, 31 Aug 2014 12:25:00 +0200 Subject: [PATCH 01/12] GenericValue: add move constructor/move assignment When C++11 is enabled, several algorithms will fail, if GenericValue is neither copyable, nor movable. Cherry-picked from 8005b55. --- include/rapidjson/document.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 92c73161..044a8fd0 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -416,6 +416,13 @@ public: //! Default constructor creates a null value. GenericValue() : data_(), flags_(kNullFlag) {} +#ifdef RAPIDJSON_CXX11 + //! Move constructor in C++11 + GenericValue(GenericValue&& rhs) : data_(rhs.data_), flags_(rhs.flags_) { + rhs.flags_ = kNullFlag; // give up contents + } +#endif + private: //! Copy constructor is not permitted. GenericValue(const GenericValue& rhs); @@ -567,6 +574,13 @@ public: return *this; } +#ifdef RAPIDJSON_CXX11 + //! Move assignment in C++11 + GenericValue& operator=(GenericValue&& rhs) { + return *this = rhs.Move(); + } +#endif + //! Assignment of constant string reference (no copy) /*! \param str Constant string reference to be assigned \note This overload is needed to avoid clashes with the generic primitive type assignment overload below. From defc3aaf9b1bbcc21b03f9a7c4253785a94fb9d0 Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Sun, 31 Aug 2014 15:04:45 +0200 Subject: [PATCH 02/12] always include "meta.h", as it is not only used for member iterators --- include/rapidjson/document.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 044a8fd0..8631c544 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -24,6 +24,7 @@ /*! \file document.h */ #include "reader.h" +#include "internal/meta.h" #include "internal/strfunc.h" #include // placement new @@ -56,7 +57,6 @@ RAPIDJSON_DIAG_OFF(effc++) #endif // RAPIDJSON_HAS_STDSTRING #ifndef RAPIDJSON_NOMEMBERITERATORCLASS -#include "internal/meta.h" #include // std::iterator, std::random_access_iterator_tag #endif From 5f6967b08396ce6a93962fd651644196ac15ce6b Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Sun, 31 Aug 2014 15:05:34 +0200 Subject: [PATCH 03/12] meta.h: disallow direct inclusion --- include/rapidjson/internal/meta.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/rapidjson/internal/meta.h b/include/rapidjson/internal/meta.h index bcff1a50..d83e1f1c 100644 --- a/include/rapidjson/internal/meta.h +++ b/include/rapidjson/internal/meta.h @@ -21,6 +21,10 @@ #ifndef RAPIDJSON_INTERNAL_META_H_ #define RAPIDJSON_INTERNAL_META_H_ +#ifndef RAPIDJSON_RAPIDJSON_H_ +#error not yet included. Do not include this file directly. +#endif + #ifdef __GNUC__ RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(effc++) From a16fe366edde17a4d2090d3b816530092b8b6c55 Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Sun, 31 Aug 2014 15:08:22 +0200 Subject: [PATCH 04/12] rapidjson.h: add RAPIDJSON_GNUC as GCC version shortcut --- include/rapidjson/rapidjson.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/include/rapidjson/rapidjson.h b/include/rapidjson/rapidjson.h index e2173a44..752744c0 100644 --- a/include/rapidjson/rapidjson.h +++ b/include/rapidjson/rapidjson.h @@ -318,7 +318,12 @@ template struct StaticAssertTest {}; /////////////////////////////////////////////////////////////////////////////// // RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF -#if defined(__clang__) || (defined(__GNUC__) && RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__) >= RAPIDJSON_VERSION_CODE(4,2,0)) +#if defined(__GNUC__) +#define RAPIDJSON_GNUC \ + RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__) +#endif + +#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,2,0)) #define RAPIDJSON_PRAGMA(x) _Pragma(RAPIDJSON_STRINGIFY(x)) #define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(GCC diagnostic x) @@ -326,7 +331,7 @@ template struct StaticAssertTest {}; RAPIDJSON_DIAG_PRAGMA(ignored RAPIDJSON_STRINGIFY(RAPIDJSON_JOIN(-W,x))) // push/pop support in Clang and GCC>=4.6 -#if defined(__clang__) || (defined(__GNUC__) && RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__) >= RAPIDJSON_VERSION_CODE(4,6,0)) +#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) #define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push) #define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop) #else // GCC >= 4.2, < 4.6 From 5656078a38b07013b4a1e21c6b816f3239170c2c Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Sun, 31 Aug 2014 15:07:36 +0200 Subject: [PATCH 05/12] detect rvalue reference support (RAPIDJSON_HAS_CXX11_RVALUE_REFS) --- include/rapidjson/document.h | 4 ++-- include/rapidjson/internal/meta.h | 4 ++-- include/rapidjson/rapidjson.h | 20 ++++++++++++++++++++ 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 8631c544..1ce4ef22 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -416,7 +416,7 @@ public: //! Default constructor creates a null value. GenericValue() : data_(), flags_(kNullFlag) {} -#ifdef RAPIDJSON_CXX11 +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS //! Move constructor in C++11 GenericValue(GenericValue&& rhs) : data_(rhs.data_), flags_(rhs.flags_) { rhs.flags_ = kNullFlag; // give up contents @@ -574,7 +574,7 @@ public: return *this; } -#ifdef RAPIDJSON_CXX11 +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS //! Move assignment in C++11 GenericValue& operator=(GenericValue&& rhs) { return *this = rhs.Move(); diff --git a/include/rapidjson/internal/meta.h b/include/rapidjson/internal/meta.h index d83e1f1c..3e6c9313 100644 --- a/include/rapidjson/internal/meta.h +++ b/include/rapidjson/internal/meta.h @@ -34,7 +34,7 @@ RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(6334) #endif -#ifdef RAPIDJSON_HAS_CXX11_TYPETRAITS +#if RAPIDJSON_HAS_CXX11_TYPETRAITS #include #endif @@ -102,7 +102,7 @@ template struct IsPointer : TrueType {}; /////////////////////////////////////////////////////////////////////////////// // IsBaseOf // -#ifdef RAPIDJSON_HAS_CXX11_TYPETRAITS +#if RAPIDJSON_HAS_CXX11_TYPETRAITS template struct IsBaseOf : BoolType< ::std::is_base_of::value> {}; diff --git a/include/rapidjson/rapidjson.h b/include/rapidjson/rapidjson.h index 752744c0..7328c4e1 100644 --- a/include/rapidjson/rapidjson.h +++ b/include/rapidjson/rapidjson.h @@ -357,6 +357,26 @@ template struct StaticAssertTest {}; #endif // RAPIDJSON_DIAG_* +/////////////////////////////////////////////////////////////////////////////// +// C++11 features + +#ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS +#if defined(__clang__) +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS __has_feature(cxx_rvalue_references) +#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ + (defined(_MSC_VER) && _MSC_VER >= 1600) + +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1 +#else +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0 +#endif +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + +// no automatic detection, yet +#ifndef RAPIDJSON_HAS_CXX11_TYPETRAITS +#define RAPIDJSON_HAS_CXX11_TYPETRAITS 0 +#endif + //!@endcond /////////////////////////////////////////////////////////////////////////////// From c1c9ba7c59534905c37cb62d87bb946e76e00169 Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Sun, 31 Aug 2014 15:09:18 +0200 Subject: [PATCH 06/12] always define RAPIDJSON_HAS_STDSTRING (default: 0) --- include/rapidjson/document.h | 14 ++++++++------ test/unittest/valuetest.cpp | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 1ce4ef22..5487918d 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -39,15 +39,17 @@ RAPIDJSON_DIAG_OFF(effc++) /////////////////////////////////////////////////////////////////////////////// // RAPIDJSON_HAS_STDSTRING +#ifndef RAPIDJSON_HAS_STDSTRING #ifdef RAPIDJSON_DOXYGEN_RUNNING #define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation +#else +#define RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default #endif -#ifdef RAPIDJSON_HAS_STDSTRING /*! \def RAPIDJSON_HAS_STDSTRING \ingroup RAPIDJSON_CONFIG \brief Enable RapidJSON support for \c std::string - By defining this preprocessor symbol, several convenience functions for using + By defining this preprocessor symbol to \c 1, several convenience functions for using \ref rapidjson::GenericValue with \c std::string are enabled, especially for construction and comparison. @@ -363,7 +365,7 @@ inline GenericStringRef StringRef(const CharType* str, size_t length) return GenericStringRef(str, SizeType(length)); } -#ifdef RAPIDJSON_HAS_STDSTRING +#if RAPIDJSON_HAS_STDSTRING //! Mark a string object as constant string /*! Mark a string object (e.g. \c std::string) as a "string literal". This function can be used to avoid copying a string to be referenced as a @@ -524,7 +526,7 @@ public: //! Constructor for copy-string (i.e. do make a copy of string) GenericValue(const Ch*s, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s), allocator); } -#ifdef RAPIDJSON_HAS_STDSTRING +#if RAPIDJSON_HAS_STDSTRING //! Constructor for copy-string from a string object (i.e. do make a copy of string) /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. */ @@ -689,7 +691,7 @@ public: //! Equal-to operator with const C-string pointer bool operator==(const Ch* rhs) const { return *this == GenericValue(StringRef(rhs)); } -#ifdef RAPIDJSON_HAS_STDSTRING +#if RAPIDJSON_HAS_STDSTRING //! Equal-to operator with string object /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. */ @@ -1303,7 +1305,7 @@ int z = a[0u].GetInt(); // This works too. */ GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(s, internal::StrLen(s), allocator); } -#ifdef RAPIDJSON_HAS_STDSTRING +#if RAPIDJSON_HAS_STDSTRING //! Set this value as a string by copying from source string. /*! \param s source string. \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). diff --git a/test/unittest/valuetest.cpp b/test/unittest/valuetest.cpp index 93248134..53a196f2 100644 --- a/test/unittest/valuetest.cpp +++ b/test/unittest/valuetest.cpp @@ -558,7 +558,7 @@ TEST(Value, String) { EXPECT_STREQ("World", w.GetString()); EXPECT_EQ(5u, w.GetStringLength()); -#ifdef RAPIDJSON_HAS_STDSTRING +#if RAPIDJSON_HAS_STDSTRING { std::string str = "Hello World"; str[5] = '\0'; From a9d2b751791430a48db51ea45526319e7e6c2878 Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Sun, 31 Aug 2014 17:18:26 +0200 Subject: [PATCH 07/12] valuetest: avoid underscores in GoogleTest tests See https://code.google.com/p/googletest/wiki/FAQ#Why_should_not_test_case_names_and_test_names_contain_underscore --- test/unittest/valuetest.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/unittest/valuetest.cpp b/test/unittest/valuetest.cpp index 53a196f2..7e54bbf8 100644 --- a/test/unittest/valuetest.cpp +++ b/test/unittest/valuetest.cpp @@ -24,7 +24,7 @@ using namespace rapidjson; -TEST(Value, default_constructor) { +TEST(Value, DefaultConstructor) { Value x; EXPECT_EQ(kNullType, x.GetType()); EXPECT_TRUE(x.IsNull()); @@ -38,7 +38,7 @@ TEST(Value, default_constructor) { // Value y = x; //} -TEST(Value, assignment_operator) { +TEST(Value, AssignmentOperator) { Value x(1234); Value y; y = x; @@ -81,7 +81,7 @@ void TestUnequal(const A& a, const B& b) { EXPECT_TRUE (b != a); } -TEST(Value, equalto_operator) { +TEST(Value, EqualtoOperator) { Value::AllocatorType allocator; Value x(kObjectType); x.AddMember("hello", "world", allocator) From b5f9d6076596c5c2b14daa99c33fc01fa69b54e0 Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Sun, 31 Aug 2014 17:23:15 +0200 Subject: [PATCH 08/12] GenericValue: add rvalue-ref overloads to AddMember/PushBack Directly allows temporary GenericValues as parameters: v.AddMember("foo", Value(s.c_str(),alloc), alloc); --- include/rapidjson/document.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 5487918d..b6edb4ab 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -911,6 +911,23 @@ public: return *this; } +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericValue& AddMember(GenericValue&& name, GenericValue&& value, Allocator& allocator) { + return AddMember(name, value, allocator); + } + GenericValue& AddMember(GenericValue&& name, GenericValue& value, Allocator& allocator) { + return AddMember(name, value, allocator); + } + GenericValue& AddMember(GenericValue& name, GenericValue&& value, Allocator& allocator) { + return AddMember(name, value, allocator); + } + GenericValue& AddMember(StringRefType name, GenericValue&& value, Allocator& allocator) { + GenericValue n(name); + return AddMember(n, value, allocator); + } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + + //! Add a member (name-value pair) to the object. /*! \param name A constant string reference as name of member. \param value Value of any type. @@ -1151,6 +1168,12 @@ int z = a[0u].GetInt(); // This works too. return *this; } +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericValue& PushBack(GenericValue&& value, Allocator& allocator) { + return PushBack(value, allocator); + } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Append a constant string reference at the end of the array. /*! \param value Constant string reference to be appended. \param allocator Allocator for reallocating memory. It must be the same one used previously. Commonly use GenericDocument::GetAllocator(). From 36031b1b6f12b38a0e92cd6fc8293f66725dc465 Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Sun, 31 Aug 2014 17:19:36 +0200 Subject: [PATCH 09/12] valuetest: add tests for rvalue references, reenable erase/remove pattern --- test/unittest/valuetest.cpp | 77 +++++++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 3 deletions(-) diff --git a/test/unittest/valuetest.cpp b/test/unittest/valuetest.cpp index 7e54bbf8..0023a7cf 100644 --- a/test/unittest/valuetest.cpp +++ b/test/unittest/valuetest.cpp @@ -38,6 +38,31 @@ TEST(Value, DefaultConstructor) { // Value y = x; //} +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS +TEST(Value, MoveConstructor) { + typedef GenericValue, CrtAllocator> Value; + Value::AllocatorType allocator; + + Value x((Value(kArrayType))); + x.Reserve(4u, allocator); + x.PushBack(1, allocator).PushBack(2, allocator).PushBack(3, allocator).PushBack(4, allocator); + EXPECT_TRUE(x.IsArray()); + EXPECT_EQ(4u, x.Size()); + + // Value y(x); // should not compile + Value y(std::move(x)); + EXPECT_TRUE(x.IsNull()); + EXPECT_TRUE(y.IsArray()); + EXPECT_EQ(4u, y.Size()); + + // Value z = y; // should not compile + Value z = std::move(y); + EXPECT_TRUE(y.IsNull()); + EXPECT_TRUE(z.IsArray()); + EXPECT_EQ(4u, z.Size()); +} +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + TEST(Value, AssignmentOperator) { Value x(1234); Value y; @@ -63,6 +88,22 @@ TEST(Value, AssignmentOperator) { y = StringRef(mstr); EXPECT_TRUE(y.IsString()); EXPECT_EQ(y.GetString(),mstr); + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + // C++11 move assignment + x = Value("World"); + EXPECT_TRUE(x.IsString()); + EXPECT_STREQ("World", x.GetString()); + + x = std::move(y); + EXPECT_TRUE(y.IsNull()); + EXPECT_TRUE(x.IsString()); + EXPECT_EQ(x.GetString(), mstr); + + y = std::move(Value().SetInt(1234)); + EXPECT_TRUE(y.IsInt()); + EXPECT_EQ(1234, y); +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS } template @@ -646,6 +687,21 @@ TEST(Value, Array) { EXPECT_TRUE(y[4u].IsString()); EXPECT_STREQ("foo", y[4u].GetString()); +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + // PushBack(GenericValue&&, Allocator&); + { + Value y(kArrayType); + y.PushBack(Value(true), allocator); + y.PushBack(std::move(Value(kArrayType).PushBack(Value(1), allocator).PushBack("foo", allocator)), allocator); + EXPECT_EQ(2u, y.Size()); + EXPECT_TRUE(y[0u].IsTrue()); + EXPECT_TRUE(y[1u].IsArray()); + EXPECT_EQ(2u, y[1u].Size()); + EXPECT_TRUE(y[1u][0u].IsInt()); + EXPECT_TRUE(y[1u][1u].IsString()); + } +#endif + // iterator Value::ValueIterator itr = x.Begin(); EXPECT_TRUE(itr != x.End()); @@ -754,7 +810,6 @@ TEST(Value, Array) { } // Working in gcc without C++11, but VS2013 cannot compile. To be diagnosed. -#if 0 // http://en.wikipedia.org/wiki/Erase-remove_idiom x.Clear(); for (int i = 0; i < 10; i++) @@ -763,11 +818,11 @@ TEST(Value, Array) { else x.PushBack(Value(kNullType).Move(), allocator); - x.Erase(std::remove(x.Begin(), x.End(), Value(kNullType)), x.End()); + const Value null(kNullType); + x.Erase(std::remove(x.Begin(), x.End(), null), x.End()); EXPECT_EQ(5u, x.Size()); for (int i = 0; i < 5; i++) EXPECT_EQ(i * 2, x[i]); -#endif // SetArray() Value z; @@ -821,6 +876,22 @@ TEST(Value, Object) { EXPECT_EQ(8u, o.MemberCount()); } +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + // AddMember(GenericValue&&, ...) variants + { + Value o(kObjectType); + o.AddMember(Value("true"), Value(true), allocator); + o.AddMember(Value("false"), Value(false).Move(), allocator); // value is lvalue ref + o.AddMember(Value("int").Move(), Value(-1), allocator); // name is lvalue ref + o.AddMember("uint", std::move(Value().SetUint(1u)), allocator); // name is literal, value is rvalue + EXPECT_TRUE(o["true"].GetBool()); + EXPECT_FALSE(o["false"].GetBool()); + EXPECT_EQ(-1, o["int"].GetInt()); + EXPECT_EQ(1u, o["uint"].GetUint()); + EXPECT_EQ(4u, o.MemberCount()); + } +#endif + // Tests a member with null character Value name; const Value C0D("C\0D", 3); From 5672d24651284693f2d0ee1ed139ea7b50f9108b Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Sun, 31 Aug 2014 17:42:18 +0200 Subject: [PATCH 10/12] GenericValue: add RAPIDJSON_NOEXCEPT Added basic detection of `noexcept` support for some compilers, added corresponding RAPIDJSON_NOEXCEPT annotations to * non-allocating constructors * (move) assignment * Swap --- build/Doxyfile | 3 ++- include/rapidjson/document.h | 32 ++++++++++++++++---------------- include/rapidjson/rapidjson.h | 16 ++++++++++++++++ 3 files changed, 34 insertions(+), 17 deletions(-) diff --git a/build/Doxyfile b/build/Doxyfile index 6827b51d..e34a3ffe 100644 --- a/build/Doxyfile +++ b/build/Doxyfile @@ -2004,7 +2004,8 @@ PREDEFINED = \ # definition found in the source code. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -EXPAND_AS_DEFINED = +EXPAND_AS_DEFINED = \ + RAPIDJSON_NOEXCEPT # If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will # remove all references to function-like macros that are alone on a line, have diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index b6edb4ab..09187990 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -416,11 +416,11 @@ public: //@{ //! Default constructor creates a null value. - GenericValue() : data_(), flags_(kNullFlag) {} + GenericValue() RAPIDJSON_NOEXCEPT : data_(), flags_(kNullFlag) {} #if RAPIDJSON_HAS_CXX11_RVALUE_REFS //! Move constructor in C++11 - GenericValue(GenericValue&& rhs) : data_(rhs.data_), flags_(rhs.flags_) { + GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_), flags_(rhs.flags_) { rhs.flags_ = kNullFlag; // give up contents } #endif @@ -436,7 +436,7 @@ public: \param type Type of the value. \note Default content for number is zero. */ - GenericValue(Type type) : data_(), flags_() { + GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_(), flags_() { static const unsigned defaultFlags[7] = { kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kConstStringFlag, kNumberAnyFlag @@ -463,9 +463,9 @@ public: */ #ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen template - explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame))) + explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame))) RAPIDJSON_NOEXCEPT #else - explicit GenericValue(bool b) + explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT #endif : data_(), flags_(b ? kTrueFlag : kFalseFlag) { // safe-guard against failing SFINAE @@ -473,21 +473,21 @@ public: } //! Constructor for int value. - explicit GenericValue(int i) : data_(), flags_(kNumberIntFlag) { + explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberIntFlag) { data_.n.i64 = i; if (i >= 0) flags_ |= kUintFlag | kUint64Flag; } //! Constructor for unsigned value. - explicit GenericValue(unsigned u) : data_(), flags_(kNumberUintFlag) { + explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUintFlag) { data_.n.u64 = u; if (!(u & 0x80000000)) flags_ |= kIntFlag | kInt64Flag; } //! Constructor for int64_t value. - explicit GenericValue(int64_t i64) : data_(), flags_(kNumberInt64Flag) { + explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberInt64Flag) { data_.n.i64 = i64; if (i64 >= 0) { flags_ |= kNumberUint64Flag; @@ -501,7 +501,7 @@ public: } //! Constructor for uint64_t value. - explicit GenericValue(uint64_t u64) : data_(), flags_(kNumberUint64Flag) { + explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUint64Flag) { data_.n.u64 = u64; if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000))) flags_ |= kInt64Flag; @@ -512,13 +512,13 @@ public: } //! Constructor for double value. - explicit GenericValue(double d) : data_(), flags_(kNumberDoubleFlag) { data_.n.d = d; } + explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberDoubleFlag) { data_.n.d = d; } //! Constructor for constant string (i.e. do not make a copy of string) - GenericValue(const Ch* s, SizeType length) : data_(), flags_() { SetStringRaw(StringRef(s, length)); } + GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_(), flags_() { SetStringRaw(StringRef(s, length)); } //! Constructor for constant string (i.e. do not make a copy of string) - explicit GenericValue(StringRefType s) : data_(), flags_() { SetStringRaw(s); } + explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_(), flags_() { SetStringRaw(s); } //! Constructor for copy-string (i.e. do make a copy of string) GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s, length), allocator); } @@ -569,7 +569,7 @@ public: //! Assignment with move semantics. /*! \param rhs Source of the assignment. It will become a null value after assignment. */ - GenericValue& operator=(GenericValue& rhs) { + GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT { RAPIDJSON_ASSERT(this != &rhs); this->~GenericValue(); RawAssign(rhs); @@ -578,7 +578,7 @@ public: #if RAPIDJSON_HAS_CXX11_RVALUE_REFS //! Move assignment in C++11 - GenericValue& operator=(GenericValue&& rhs) { + GenericValue& operator=(GenericValue&& rhs) RAPIDJSON_NOEXCEPT { return *this = rhs.Move(); } #endif @@ -588,7 +588,7 @@ public: \note This overload is needed to avoid clashes with the generic primitive type assignment overload below. \see GenericStringRef, operator=(T) */ - GenericValue& operator=(StringRefType str) { + GenericValue& operator=(StringRefType str) RAPIDJSON_NOEXCEPT { GenericValue s(str); return *this = s; } @@ -631,7 +631,7 @@ public: \param other Another value. \note Constant complexity. */ - GenericValue& Swap(GenericValue& other) { + GenericValue& Swap(GenericValue& other) RAPIDJSON_NOEXCEPT { GenericValue temp; temp.RawAssign(*this); RawAssign(other); diff --git a/include/rapidjson/rapidjson.h b/include/rapidjson/rapidjson.h index 7328c4e1..9aa9204a 100644 --- a/include/rapidjson/rapidjson.h +++ b/include/rapidjson/rapidjson.h @@ -372,6 +372,22 @@ template struct StaticAssertTest {}; #endif #endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS +#ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT +#if defined(__clang__) +#define RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept) +#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) +// (defined(_MSC_VER) && _MSC_VER >= ????) // not yet supported +#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1 +#else +#define RAPIDJSON_HAS_CXX11_NOEXCEPT 0 +#endif +#endif +#if RAPIDJSON_HAS_CXX11_NOEXCEPT +#define RAPIDJSON_NOEXCEPT noexcept +#else +#define RAPIDJSON_NOEXCEPT /* noexcept */ +#endif // RAPIDJSON_HAS_CXX11_NOEXCEPT + // no automatic detection, yet #ifndef RAPIDJSON_HAS_CXX11_TYPETRAITS #define RAPIDJSON_HAS_CXX11_TYPETRAITS 0 From 56625bd9f01232eea6d5a3331bb41e1fb62a3473 Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Sun, 31 Aug 2014 22:00:39 +0200 Subject: [PATCH 11/12] GenericValue: add some more RAPIDJSON_NOEXCEPT * Move() * RawAssign() * SetStringRaw() --- include/rapidjson/document.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 09187990..4bdb60f2 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -641,7 +641,7 @@ public: //! Prepare Value for move semantics /*! \return *this */ - GenericValue& Move() { return *this; } + GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; } //@} //!@name Equal-to and not-equal-to operators @@ -1494,7 +1494,7 @@ private: } //! Initialize this value as constant string, without calling destructor. - void SetStringRaw(StringRefType s) { + void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT { flags_ = kConstStringFlag; data_.s.str = s; data_.s.length = s.length; @@ -1510,7 +1510,7 @@ private: } //! Assignment without calling destructor - void RawAssign(GenericValue& rhs) { + void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT { data_ = rhs.data_; flags_ = rhs.flags_; rhs.flags_ = kNullFlag; From 8ae2266c3baa40fc2fa1b38244aad6f00cf2c235 Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Sun, 31 Aug 2014 22:01:57 +0200 Subject: [PATCH 12/12] GenericStringRef: add NOEXCEPT, add ASSERT * constructor from array is RAPIDJSON_NOEXCEPT * constructor from plain pointer missed an assert --- include/rapidjson/document.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 4bdb60f2..d139ea75 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -279,7 +279,7 @@ struct GenericStringRef { GenericValue instead. */ template - GenericStringRef(const CharType (&str)[N]) + GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT : s(str), length(N-1) {} //! Explicitly create string reference from \c const character pointer @@ -302,7 +302,7 @@ struct GenericStringRef { GenericValue instead. */ explicit GenericStringRef(const CharType* str) - : s(str), length(internal::StrLen(str)){} + : s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != NULL); } //! Create constant string reference from pointer and length /*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue