From e8445e0bbc9a5450ab1d22a27cc71bab8347edbb Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Fri, 24 Oct 2014 13:55:26 +0200 Subject: [PATCH 1/2] GenericValue: improve operator[] disambiguation In the original disambiguation fix for `GenericValue::operator[]` (#170), the documentation has been missing, which led to quite badly rendered Doxygen pages. During a cleanup, I've realized that a much simpler disambiguation is possible: ````cpp GenericValue& operator[](SizeType idx); // array template GenericValue& operator[](T* name); // object ```` This approach works, as non-template functions are preferred over template functions. In order to improve the error messages, the pointer type is restricted to `(const) Ch`. Update `tutorial.md` to drop the ambiguity warning. --- doc/tutorial.md | 4 +--- include/rapidjson/document.h | 33 ++++++++++++++------------------- 2 files changed, 15 insertions(+), 22 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 857895d1..40e061ca 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -121,9 +121,7 @@ In the following, details about querying individual types are discussed. By default, `SizeType` is typedef of `unsigned`. In most systems, array is limited to store up to 2^32-1 elements. -You may access the elements in array by integer literal, for example, `a[1]`, `a[2]`. However, `a[0]` will generate a compiler error. It is because two overloaded operators `operator[](SizeType)` and `operator[](const char*)` is available, and C++ can treat `0` as a null pointer. Workarounds: -* `a[SizeType(0)]` -* `a[0u]` +You may access the elements in array by integer literal, for example, `a[0]`, `a[1]`, `a[2]`. Array is similar to `std::vector`, instead of using indices, you may also use iterator to access all the elements. ~~~~~~~~~~cpp diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index d0ead391..6f2c1bad 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -795,15 +795,6 @@ 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. @@ -812,20 +803,14 @@ private: A better approach is to use FindMember(). \note Linear time complexity. */ - - GenericValue& DoIndex(const Ch* name, internal::TrueType) { + template + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch> >),(GenericValue&)) operator[](T* name) { GenericValue n(StringRef(name)); return (*this)[n]; } + template + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch> >),(const GenericValue&)) operator[](T* 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(). @@ -1150,6 +1135,16 @@ public: data_.a.size = 0; } + //! Get an element from array by index. + /*! \param index Zero-based index of element. + */ + 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; } From 6bd5ecb08ce5b6004bab6021d88a183911473def Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Fri, 24 Oct 2014 14:45:48 +0200 Subject: [PATCH 2/2] GenericValue: improve documentation for operator[] --- include/rapidjson/document.h | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 6f2c1bad..0a44d3e4 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -795,8 +795,9 @@ public: //! Check whether the object is empty. bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; } - //! Get the value associated with the name. - /*! + //! Get a value from an object associated with the name. + /*! \pre IsObject() == true + \tparam T Either \c Ch or \c const \c Ch (template used for disambiguation with \ref operator[](SizeType)) \note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7. Since 0.2, if the name is not correct, it will assert. If user is unsure whether a member exists, user should use HasMember() first. @@ -811,10 +812,15 @@ public: template RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch> >),(const GenericValue&)) operator[](T* name) const { return const_cast(*this)[name]; } + //! Get a value from an object associated with the name. + /*! \pre IsObject() == true + \tparam SourceAllocator Allocator of the \c name value -public: - // This version is faster because it does not need a StrLen(). - // It can also handle string with null character. + \note Compared to \ref operator[](T*), this version is faster because it does not need a StrLen(). + And it can also handle strings with embedded null characters. + + \note Linear time complexity. + */ template GenericValue& operator[](const GenericValue& name) { MemberIterator member = FindMember(name); @@ -1136,7 +1142,9 @@ public: } //! Get an element from array by index. - /*! \param index Zero-based index of element. + /*! \pre IsArray() == true + \param index Zero-based index of element. + \see operator[](T*) */ GenericValue& operator[](SizeType index) { RAPIDJSON_ASSERT(IsArray());