diff options
author | Milo Yip <miloyip@gmail.com> | 2014-09-03 05:37:35 +0400 |
---|---|---|
committer | Milo Yip <miloyip@gmail.com> | 2014-09-03 05:37:35 +0400 |
commit | bc9d7866be368e54671243b34f746bdada2afbe1 (patch) | |
tree | 3c945f7c02f91e7ded9dcba4f207be48e69a6d4e | |
parent | 15d70d6a7b8124f2a7fb309abd66c2e5063e0535 (diff) | |
parent | 8ae2266c3baa40fc2fa1b38244aad6f00cf2c235 (diff) |
Merge pull request #128 from pah/feature/cxx11-move
Initial C++11 move support
-rw-r--r-- | build/Doxyfile | 3 | ||||
-rw-r--r-- | include/rapidjson/document.h | 91 | ||||
-rw-r--r-- | include/rapidjson/internal/meta.h | 8 | ||||
-rw-r--r-- | include/rapidjson/rapidjson.h | 45 | ||||
-rw-r--r-- | test/unittest/valuetest.cpp | 85 |
5 files changed, 194 insertions, 38 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 87ff58a4..13acb381 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 <new> // placement new
@@ -38,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.
@@ -56,7 +59,6 @@ RAPIDJSON_DIAG_OFF(effc++) #endif // RAPIDJSON_HAS_STDSTRING
#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
-#include "internal/meta.h"
#include <iterator> // std::iterator, std::random_access_iterator_tag
#endif
@@ -277,7 +279,7 @@ struct GenericStringRef { GenericValue instead.
*/
template<SizeType N>
- 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
@@ -300,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
@@ -363,7 +365,7 @@ inline GenericStringRef<CharType> StringRef(const CharType* str, size_t length) return GenericStringRef<CharType>(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
@@ -430,7 +432,14 @@ 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) RAPIDJSON_NOEXCEPT : data_(rhs.data_), flags_(rhs.flags_) {
+ rhs.flags_ = kNullFlag; // give up contents
+ }
+#endif
private:
//! Copy constructor is not permitted.
@@ -443,7 +452,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
@@ -470,9 +479,9 @@ public: */
#ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen
template <typename T>
- explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame<T,bool>)))
+ explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame<T,bool>))) RAPIDJSON_NOEXCEPT
#else
- explicit GenericValue(bool b)
+ explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT
#endif
: data_(), flags_(b ? kTrueFlag : kFalseFlag) {
// safe-guard against failing SFINAE
@@ -480,21 +489,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;
@@ -508,7 +517,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;
@@ -519,13 +528,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); }
@@ -533,7 +542,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.
*/
@@ -576,19 +585,26 @@ 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);
return *this;
}
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ //! Move assignment in C++11
+ GenericValue& operator=(GenericValue&& rhs) RAPIDJSON_NOEXCEPT {
+ 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.
\see GenericStringRef, operator=(T)
*/
- GenericValue& operator=(StringRefType str) {
+ GenericValue& operator=(StringRefType str) RAPIDJSON_NOEXCEPT {
GenericValue s(str);
return *this = s;
}
@@ -631,7 +647,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);
@@ -641,7 +657,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
@@ -693,7 +709,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.
*/
@@ -921,6 +937,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.
@@ -1162,6 +1195,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().
@@ -1316,7 +1355,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().
@@ -1502,7 +1541,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;
@@ -1526,7 +1565,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;
diff --git a/include/rapidjson/internal/meta.h b/include/rapidjson/internal/meta.h index 578b6702..dbe5450d 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 <rapidjson.h> not yet included. Do not include this file directly.
+#endif
+
#ifdef __GNUC__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
@@ -30,7 +34,7 @@ RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(6334)
#endif
-#ifdef RAPIDJSON_HAS_CXX11_TYPETRAITS
+#if RAPIDJSON_HAS_CXX11_TYPETRAITS
#include <type_traits>
#endif
@@ -100,7 +104,7 @@ template <typename T> struct IsPointer<T*> : TrueType {}; ///////////////////////////////////////////////////////////////////////////////
// IsBaseOf
//
-#ifdef RAPIDJSON_HAS_CXX11_TYPETRAITS
+#if RAPIDJSON_HAS_CXX11_TYPETRAITS
template <typename B, typename D> struct IsBaseOf
: BoolType< ::std::is_base_of<B,D>::value> {};
diff --git a/include/rapidjson/rapidjson.h b/include/rapidjson/rapidjson.h index e2173a44..9aa9204a 100644 --- a/include/rapidjson/rapidjson.h +++ b/include/rapidjson/rapidjson.h @@ -318,7 +318,12 @@ template<int x> 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<int x> 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
@@ -352,6 +357,42 @@ template<int x> 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
+
+#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
+#endif
+
//!@endcond
///////////////////////////////////////////////////////////////////////////////
diff --git a/test/unittest/valuetest.cpp b/test/unittest/valuetest.cpp index f803c950..c40df876 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,32 @@ TEST(Value, default_constructor) { // Value y = x;
//}
-TEST(Value, assignment_operator) {
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+TEST(Value, MoveConstructor) {
+ typedef GenericValue<UTF8<>, 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;
y = x;
@@ -63,6 +88,22 @@ TEST(Value, assignment_operator) { 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 <typename A, typename B>
@@ -81,7 +122,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)
@@ -555,7 +596,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';
@@ -643,6 +684,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());
@@ -751,7 +807,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++)
@@ -760,11 +815,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;
@@ -818,6 +873,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);
|