diff --git a/example/tutorial/tutorial.cpp b/example/tutorial/tutorial.cpp index fc96874..b72db00 100644 --- a/example/tutorial/tutorial.cpp +++ b/example/tutorial/tutorial.cpp @@ -72,12 +72,8 @@ int main(int, char*[]) { for (SizeType i = 0; i < a.Size(); i++) // rapidjson uses SizeType instead of size_t. printf("a[%d] = %d\n", i, a[i].GetInt()); - // Note: - //int x = a[0].GetInt(); // Error: operator[ is ambiguous, as 0 also mean a null pointer of const char* type. - int y = a[SizeType(0)].GetInt(); // Cast to SizeType will work. - int z = a[0u].GetInt(); // This works too. + int y = a[0].GetInt(); (void)y; - (void)z; // Iterating array with iterators printf("a = "); diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 4a3a1a2..d0ead39 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -451,7 +451,7 @@ public: \param type Type of the value. \note Default content for number is zero. */ - GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_(), flags_() { + explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_(), flags_() { static const unsigned defaultFlags[7] = { kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kConstStringFlag, kNumberAnyFlag @@ -795,6 +795,15 @@ public: //! Check whether the object is empty. bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; } + template + GenericValue& operator[](T t) { + return DoIndex(t, internal::IsPointer()); + } + + template + const GenericValue& operator[](T t) const { return const_cast(*this)[t]; } + +private: //! Get the value associated with the name. /*! \note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7. @@ -803,12 +812,22 @@ public: A better approach is to use FindMember(). \note Linear time complexity. */ - GenericValue& operator[](const Ch* name) { + + GenericValue& DoIndex(const Ch* name, internal::TrueType) { GenericValue n(StringRef(name)); return (*this)[n]; } - const GenericValue& operator[](const Ch* name) const { return const_cast(*this)[name]; } + //! Get an element from array by index. + /*! \param index Zero-based index of element. + */ + GenericValue& DoIndex(SizeType index, internal::FalseType) { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(index < data_.a.size); + return data_.a.elements[index]; + } + +public: // This version is faster because it does not need a StrLen(). // It can also handle string with null character. template @@ -1131,23 +1150,6 @@ public: data_.a.size = 0; } - //! Get an element from array by index. - /*! \param index Zero-based index of element. -\code -Value a(kArrayType); -a.PushBack(123); -int x = a[0].GetInt(); // Error: operator[ is ambiguous, as 0 also mean a null pointer of const char* type. -int y = a[SizeType(0)].GetInt(); // Cast to SizeType will work. -int z = a[0u].GetInt(); // This works too. -\endcode - */ - GenericValue& operator[](SizeType index) { - RAPIDJSON_ASSERT(IsArray()); - RAPIDJSON_ASSERT(index < data_.a.size); - return data_.a.elements[index]; - } - const GenericValue& operator[](SizeType index) const { return const_cast(*this)[index]; } - //! Element iterator /*! \pre IsArray() == true */ ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements; } diff --git a/test/unittest/documenttest.cpp b/test/unittest/documenttest.cpp index 5809361..edc990a 100644 --- a/test/unittest/documenttest.cpp +++ b/test/unittest/documenttest.cpp @@ -218,7 +218,7 @@ TEST(Document, UTF16_Document) { json.Parse(L"[{\"created_at\":\"Wed Oct 30 17:13:20 +0000 2012\"}]"); ASSERT_TRUE(json.IsArray()); - GenericValue< UTF16<> >& v = json[0u]; + GenericValue< UTF16<> >& v = json[0]; ASSERT_TRUE(v.IsObject()); GenericValue< UTF16<> >& s = v[L"created_at"]; diff --git a/test/unittest/valuetest.cpp b/test/unittest/valuetest.cpp index c40df87..6dc6c87 100644 --- a/test/unittest/valuetest.cpp +++ b/test/unittest/valuetest.cpp @@ -672,17 +672,17 @@ TEST(Value, Array) { EXPECT_FALSE(y.Empty()); EXPECT_EQ(5u, y.Size()); EXPECT_TRUE(x[SizeType(0)].IsNull()); - EXPECT_TRUE(x[1u].IsTrue()); - EXPECT_TRUE(x[2u].IsFalse()); - EXPECT_TRUE(x[3u].IsInt()); - EXPECT_EQ(123, x[3u].GetInt()); + EXPECT_TRUE(x[1].IsTrue()); + EXPECT_TRUE(x[2].IsFalse()); + EXPECT_TRUE(x[3].IsInt()); + EXPECT_EQ(123, x[3].GetInt()); EXPECT_TRUE(y[SizeType(0)].IsNull()); - EXPECT_TRUE(y[1u].IsTrue()); - EXPECT_TRUE(y[2u].IsFalse()); - EXPECT_TRUE(y[3u].IsInt()); - EXPECT_EQ(123, y[3u].GetInt()); - EXPECT_TRUE(y[4u].IsString()); - EXPECT_STREQ("foo", y[4u].GetString()); + EXPECT_TRUE(y[1].IsTrue()); + EXPECT_TRUE(y[2].IsFalse()); + EXPECT_TRUE(y[3].IsInt()); + EXPECT_EQ(123, y[3].GetInt()); + EXPECT_TRUE(y[4].IsString()); + EXPECT_STREQ("foo", y[4].GetString()); #if RAPIDJSON_HAS_CXX11_RVALUE_REFS // PushBack(GenericValue&&, Allocator&); @@ -691,11 +691,11 @@ TEST(Value, Array) { 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()); + EXPECT_TRUE(y[0].IsTrue()); + EXPECT_TRUE(y[1].IsArray()); + EXPECT_EQ(2u, y[1].Size()); + EXPECT_TRUE(y[1][0].IsInt()); + EXPECT_TRUE(y[1][1].IsString()); } #endif @@ -741,9 +741,9 @@ TEST(Value, Array) { x.PopBack(); EXPECT_EQ(4u, x.Size()); EXPECT_TRUE(y[SizeType(0)].IsNull()); - EXPECT_TRUE(y[1u].IsTrue()); - EXPECT_TRUE(y[2u].IsFalse()); - EXPECT_TRUE(y[3u].IsInt()); + EXPECT_TRUE(y[1].IsTrue()); + EXPECT_TRUE(y[2].IsFalse()); + EXPECT_TRUE(y[3].IsInt()); // Clear() x.Clear(); @@ -764,23 +764,23 @@ TEST(Value, Array) { EXPECT_EQ(x.Begin(), itr); EXPECT_EQ(9u, x.Size()); for (int i = 0; i < 9; i++) - EXPECT_EQ(i + 1, x[i][0u].GetInt()); + EXPECT_EQ(i + 1, x[i][0].GetInt()); // Ease the last itr = x.Erase(x.End() - 1); EXPECT_EQ(x.End(), itr); EXPECT_EQ(8u, x.Size()); for (int i = 0; i < 8; i++) - EXPECT_EQ(i + 1, x[i][0u].GetInt()); + EXPECT_EQ(i + 1, x[i][0].GetInt()); // Erase the middle itr = x.Erase(x.Begin() + 4); EXPECT_EQ(x.Begin() + 4, itr); EXPECT_EQ(7u, x.Size()); for (int i = 0; i < 4; i++) - EXPECT_EQ(i + 1, x[i][0u].GetInt()); + EXPECT_EQ(i + 1, x[i][0].GetInt()); for (int i = 4; i < 7; i++) - EXPECT_EQ(i + 2, x[i][0u].GetInt()); + EXPECT_EQ(i + 2, x[i][0].GetInt()); // Erase(ValueIterator, ValueIterator) // Exhaustive test with all 0 <= first < n, first <= last <= n cases @@ -800,9 +800,9 @@ TEST(Value, Array) { size_t removeCount = last - first; EXPECT_EQ(n - removeCount, x.Size()); for (unsigned i = 0; i < first; i++) - EXPECT_EQ(i, x[i][0u].GetUint()); + EXPECT_EQ(i, x[i][0].GetUint()); for (unsigned i = first; i < n - removeCount; i++) - EXPECT_EQ(i + removeCount, x[i][0u].GetUint()); + EXPECT_EQ(i + removeCount, x[i][0].GetUint()); } } @@ -1012,7 +1012,7 @@ TEST(Value, Object) { for (; itr != x.MemberEnd(); ++itr) { int i = (itr - x.MemberBegin()) + 1; EXPECT_STREQ(itr->name.GetString(), keys[i]); - EXPECT_EQ(i, itr->value[0u].GetInt()); + EXPECT_EQ(i, itr->value[0].GetInt()); } // Erase the last @@ -1023,7 +1023,7 @@ TEST(Value, Object) { for (; itr != x.MemberEnd(); ++itr) { int i = (itr - x.MemberBegin()) + 1; EXPECT_STREQ(itr->name.GetString(), keys[i]); - EXPECT_EQ(i, itr->value[0u].GetInt()); + EXPECT_EQ(i, itr->value[0].GetInt()); } // Erase the middle @@ -1035,7 +1035,7 @@ TEST(Value, Object) { int i = (itr - x.MemberBegin()); i += (i<4) ? 1 : 2; EXPECT_STREQ(itr->name.GetString(), keys[i]); - EXPECT_EQ(i, itr->value[0u].GetInt()); + EXPECT_EQ(i, itr->value[0].GetInt()); } // EraseMember(ConstMemberIterator, ConstMemberIterator) @@ -1056,9 +1056,9 @@ TEST(Value, Object) { size_t removeCount = last - first; EXPECT_EQ(n - removeCount, x.MemberCount()); for (unsigned i = 0; i < first; i++) - EXPECT_EQ(i, x[keys[i]][0u].GetUint()); + EXPECT_EQ(i, x[keys[i]][0].GetUint()); for (unsigned i = first; i < n - removeCount; i++) - EXPECT_EQ(i + removeCount, x[keys[i+removeCount]][0u].GetUint()); + EXPECT_EQ(i + removeCount, x[keys[i+removeCount]][0].GetUint()); } }