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 ffccabaa..73a89fde 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -799,41 +799,32 @@ 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. - /*! + //! 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. 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. + //! Get a value from an object associated with the name. + /*! \pre IsObject() == true + \tparam SourceAllocator Allocator of the \c name value + + \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. */ - 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 GenericValue& operator[](const GenericValue& name) { MemberIterator member = FindMember(name); @@ -1154,6 +1145,18 @@ public: data_.a.size = 0; } + //! Get an element from array by index. + /*! \pre IsArray() == true + \param index Zero-based index of element. + \see operator[](T*) + */ + 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; }