-
Notifications
You must be signed in to change notification settings - Fork 3.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Templated accessors and range-based for #542
Merged
Merged
Changes from 15 commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
4d648fd
Add templated accessors
miloyip 513fe78
Add templated accessors for C string
miloyip c6946fd
Merge branch 'master' into issue316_templatedaccessors
miloyip 59309b5
Add GenericArray helper class with range-based for
miloyip 0b098eb
Rectify constness of Array
miloyip 2a78b4d
Fix Value.String test compilation error
miloyip 960324a
Try to fix gcc compilation error
miloyip effc8a8
Let constness of GenericArray::ValueItaertor depending on ValueType
miloyip 923db0e
Fix gcc compilation error
miloyip 1634395
Add object helper
miloyip be66450
Fix compilation errors
miloyip 6671bd5
Fix another compilation error
miloyip 4ababca
Fixed typos pointed out by @pah
miloyip 8c79fb6
Fix return type of GenericObject::AddMember()
miloyip 70f9671
Return value type for GenericObject/Array member functions
miloyip d13be6c
Change pointer to reference in GenericArray|Object
miloyip 46dc8e9
Add implicit constructors of GenericValue for GenercArray|Object
miloyip 9f6736c
Add noexcept to the constructors
miloyip File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -393,6 +393,127 @@ template <typename T> struct IsGenericValue : IsGenericValueImpl<T>::Type {}; | |
|
||
} // namespace internal | ||
|
||
/////////////////////////////////////////////////////////////////////////////// | ||
// TypeHelper | ||
|
||
namespace internal { | ||
|
||
template <typename ValueType, typename T> | ||
struct TypeHelper {}; | ||
|
||
template<typename ValueType> | ||
struct TypeHelper<ValueType, bool> { | ||
static bool Is(const ValueType& v) { return v.IsBool(); } | ||
static bool Get(const ValueType& v) { return v.GetBool(); } | ||
static ValueType& Set(ValueType& v, bool data) { return v.SetBool(data); } | ||
static ValueType& Set(ValueType& v, bool data, typename ValueType::AllocatorType&) { return v.SetBool(data); } | ||
}; | ||
|
||
template<typename ValueType> | ||
struct TypeHelper<ValueType, int> { | ||
static bool Is(const ValueType& v) { return v.IsInt(); } | ||
static int Get(const ValueType& v) { return v.GetInt(); } | ||
static ValueType& Set(ValueType& v, int data) { return v.SetInt(data); } | ||
static ValueType& Set(ValueType& v, int data, typename ValueType::AllocatorType&) { return v.SetInt(data); } | ||
}; | ||
|
||
template<typename ValueType> | ||
struct TypeHelper<ValueType, unsigned> { | ||
static bool Is(const ValueType& v) { return v.IsUint(); } | ||
static unsigned Get(const ValueType& v) { return v.GetUint(); } | ||
static ValueType& Set(ValueType& v, unsigned data) { return v.SetUint(data); } | ||
static ValueType& Set(ValueType& v, unsigned data, typename ValueType::AllocatorType&) { return v.SetUint(data); } | ||
}; | ||
|
||
template<typename ValueType> | ||
struct TypeHelper<ValueType, int64_t> { | ||
static bool Is(const ValueType& v) { return v.IsInt64(); } | ||
static int64_t Get(const ValueType& v) { return v.GetInt64(); } | ||
static ValueType& Set(ValueType& v, int64_t data) { return v.SetInt64(data); } | ||
static ValueType& Set(ValueType& v, int64_t data, typename ValueType::AllocatorType&) { return v.SetInt64(data); } | ||
}; | ||
|
||
template<typename ValueType> | ||
struct TypeHelper<ValueType, uint64_t> { | ||
static bool Is(const ValueType& v) { return v.IsUint64(); } | ||
static uint64_t Get(const ValueType& v) { return v.GetUint64(); } | ||
static ValueType& Set(ValueType& v, uint64_t data) { return v.SetUint64(data); } | ||
static ValueType& Set(ValueType& v, uint64_t data, typename ValueType::AllocatorType&) { return v.SetUint64(data); } | ||
}; | ||
|
||
template<typename ValueType> | ||
struct TypeHelper<ValueType, double> { | ||
static bool Is(const ValueType& v) { return v.IsDouble(); } | ||
static double Get(const ValueType& v) { return v.GetDouble(); } | ||
static ValueType& Set(ValueType& v, double data) { return v.SetDouble(data); } | ||
static ValueType& Set(ValueType& v, double data, typename ValueType::AllocatorType&) { return v.SetDouble(data); } | ||
}; | ||
|
||
template<typename ValueType> | ||
struct TypeHelper<ValueType, float> { | ||
static bool Is(const ValueType& v) { return v.IsFloat(); } | ||
static float Get(const ValueType& v) { return v.GetFloat(); } | ||
static ValueType& Set(ValueType& v, float data) { return v.SetFloat(data); } | ||
static ValueType& Set(ValueType& v, float data, typename ValueType::AllocatorType&) { return v.SetFloat(data); } | ||
}; | ||
|
||
template<typename ValueType> | ||
struct TypeHelper<ValueType, const typename ValueType::Ch*> { | ||
typedef const typename ValueType::Ch* StringType; | ||
static bool Is(const ValueType& v) { return v.IsString(); } | ||
static StringType Get(const ValueType& v) { return v.GetString(); } | ||
static ValueType& Set(ValueType& v, const StringType data) { return v.SetString(typename ValueType::StringRefType(data)); } | ||
static ValueType& Set(ValueType& v, const StringType data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); } | ||
}; | ||
|
||
#if RAPIDJSON_HAS_STDSTRING | ||
template<typename ValueType> | ||
struct TypeHelper<ValueType, std::basic_string<typename ValueType::Ch> > { | ||
typedef std::basic_string<typename ValueType::Ch> StringType; | ||
static bool Is(const ValueType& v) { return v.IsString(); } | ||
static StringType Get(const ValueType& v) { return v.GetString(); } | ||
static ValueType& Set(ValueType& v, const StringType& data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); } | ||
}; | ||
#endif | ||
|
||
template<typename ValueType> | ||
struct TypeHelper<ValueType, typename ValueType::Array> { | ||
typedef typename ValueType::Array ArrayType; | ||
static bool Is(const ValueType& v) { return v.IsArray(); } | ||
static ArrayType Get(ValueType& v) { return v.GetArray(); } | ||
static ValueType& Set(ValueType& v, ArrayType data) { return v.SetArray(data); } | ||
static ValueType& Set(ValueType& v, ArrayType data, typename ValueType::AllocatorType&) { return v.SetArray(data); } | ||
}; | ||
|
||
template<typename ValueType> | ||
struct TypeHelper<ValueType, typename ValueType::ConstArray> { | ||
typedef typename ValueType::ConstArray ArrayType; | ||
static bool Is(const ValueType& v) { return v.IsArray(); } | ||
static ArrayType Get(const ValueType& v) { return v.GetArray(); } | ||
}; | ||
|
||
template<typename ValueType> | ||
struct TypeHelper<ValueType, typename ValueType::Object> { | ||
typedef typename ValueType::Object ObjectType; | ||
static bool Is(const ValueType& v) { return v.IsObject(); } | ||
static ObjectType Get(ValueType& v) { return v.GetObject(); } | ||
static ValueType& Set(ValueType& v, ObjectType data) { return v.SetObject(data); } | ||
static ValueType& Set(ValueType& v, ObjectType data, typename ValueType::AllocatorType&) { return v.SetObject(data); } | ||
}; | ||
|
||
template<typename ValueType> | ||
struct TypeHelper<ValueType, typename ValueType::ConstObject> { | ||
typedef typename ValueType::ConstObject ObjectType; | ||
static bool Is(const ValueType& v) { return v.IsObject(); } | ||
static ObjectType Get(const ValueType& v) { return v.GetObject(); } | ||
}; | ||
|
||
} // namespace internal | ||
|
||
// Forward declarations | ||
template <bool, typename> class GenericArray; | ||
template <bool, typename> class GenericObject; | ||
|
||
/////////////////////////////////////////////////////////////////////////////// | ||
// GenericValue | ||
|
||
|
@@ -420,6 +541,10 @@ class GenericValue { | |
typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array. | ||
typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array. | ||
typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of itself. | ||
typedef GenericArray<false, ValueType> Array; | ||
typedef GenericArray<true, ValueType> ConstArray; | ||
typedef GenericObject<false, ValueType> Object; | ||
typedef GenericObject<true, ValueType> ConstObject; | ||
|
||
//!@name Constructors and destructor. | ||
//@{ | ||
|
@@ -845,6 +970,9 @@ class GenericValue { | |
/*! \post IsObject() == true */ | ||
GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; } | ||
|
||
//! Set this value with an object. | ||
GenericValue& SetObject(Object& o) { return *this = *o.ptr_; } | ||
|
||
//! Get the number of members in the object. | ||
SizeType MemberCount() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size; } | ||
|
||
|
@@ -1020,7 +1148,7 @@ class GenericValue { | |
RAPIDJSON_ASSERT(IsObject()); | ||
RAPIDJSON_ASSERT(name.IsString()); | ||
|
||
Object& o = data_.o; | ||
ObjectData& o = data_.o; | ||
if (o.size >= o.capacity) { | ||
if (o.capacity == 0) { | ||
o.capacity = kDefaultObjectCapacity; | ||
|
@@ -1291,14 +1419,20 @@ class GenericValue { | |
return false; | ||
} | ||
|
||
Object GetObject() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); } | ||
ConstObject GetObject() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); } | ||
|
||
//@} | ||
|
||
//!@name Array | ||
//@{ | ||
|
||
//! Set this value as an empty array. | ||
/*! \post IsArray == true */ | ||
GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; } | ||
GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; } | ||
|
||
//! Set this value with an array. | ||
GenericValue& SetArray(Array& a) { return *this = *a.ptr_; } | ||
|
||
//! Get the number of elements in array. | ||
SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; } | ||
|
@@ -1466,6 +1600,9 @@ class GenericValue { | |
return pos; | ||
} | ||
|
||
Array GetArray() { RAPIDJSON_ASSERT(IsArray()); return Array(*this); } | ||
ConstArray GetArray() const { RAPIDJSON_ASSERT(IsArray()); return ConstArray(*this); } | ||
|
||
//@} | ||
|
||
//!@name Number | ||
|
@@ -1563,6 +1700,30 @@ class GenericValue { | |
|
||
//@} | ||
|
||
//!@name Array | ||
//@{ | ||
|
||
//! Templated version for checking whether this value is type T. | ||
/*! | ||
\tparam T Either \c bool, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c float, \c const \c char*, \c std::basic_string<Ch> | ||
*/ | ||
template <typename T> | ||
bool Is() const { return internal::TypeHelper<ValueType, T>::Is(*this); } | ||
|
||
template <typename T> | ||
T Get() const { return internal::TypeHelper<ValueType, T>::Get(*this); } | ||
|
||
template <typename T> | ||
T Get() { return internal::TypeHelper<ValueType, T>::Get(*this); } | ||
|
||
template<typename T> | ||
ValueType& Set(const T& data) { return internal::TypeHelper<ValueType, T>::Set(*this, data); } | ||
|
||
template<typename T> | ||
ValueType& Set(const T& data, AllocatorType& allocator) { return internal::TypeHelper<ValueType, T>::Set(*this, data, allocator); } | ||
|
||
//@} | ||
|
||
//! Generate events of this value to a Handler. | ||
/*! This function adopts the GoF visitor pattern. | ||
Typical usage is to output this JSON value as JSON text via Writer, which is a Handler. | ||
|
@@ -1697,13 +1858,13 @@ class GenericValue { | |
double d; | ||
}; // 8 bytes | ||
|
||
struct Object { | ||
struct ObjectData { | ||
Member* members; | ||
SizeType size; | ||
SizeType capacity; | ||
}; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode | ||
|
||
struct Array { | ||
struct ArrayData { | ||
GenericValue* elements; | ||
SizeType size; | ||
SizeType capacity; | ||
|
@@ -1713,8 +1874,8 @@ class GenericValue { | |
String s; | ||
ShortString ss; | ||
Number n; | ||
Object o; | ||
Array a; | ||
ObjectData o; | ||
ArrayData a; | ||
}; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode | ||
|
||
// Initialize this value as array with initial data, without calling destructor. | ||
|
@@ -2172,6 +2333,145 @@ GenericValue<Encoding,Allocator>::GenericValue(const GenericValue<Encoding,Sourc | |
} | ||
} | ||
|
||
//! Helper class for accessing Value of array type. | ||
/*! | ||
Instance of this helper class is obtained by \c GenericValue::GetArray(). | ||
In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1. | ||
*/ | ||
template <bool Const, typename ValueT> | ||
class GenericArray { | ||
public: | ||
typedef GenericArray<true, ValueT> ConstArray; | ||
typedef GenericArray<false, ValueT> Array; | ||
typedef ValueT PlainType; | ||
typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType; | ||
typedef ValueType* ValueIterator; // This may be const or non-const iterator | ||
typedef const ValueT* ConstValueIterator; | ||
typedef typename ValueType::AllocatorType AllocatorType; | ||
typedef typename ValueType::StringRefType StringRefType; | ||
|
||
template <typename, typename> | ||
friend class GenericValue; | ||
|
||
GenericArray() : ptr_() {} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we skip the default constructors for |
||
GenericArray(const GenericArray& rhs) : ptr_(rhs.ptr_) {} | ||
GenericArray& operator=(const GenericArray& rhs) { ptr_ = rhs.ptr_; return *this; } | ||
~GenericArray() {} | ||
|
||
SizeType Size() const { return ptr_->Size(); } | ||
SizeType Capacity() const { return ptr_->Capacity(); } | ||
bool Empty() const { return ptr_->Empty(); } | ||
void Clear() const { ptr_->Clear(); } | ||
ValueType& operator[](SizeType index) const { return (*ptr_)[index]; } | ||
ValueIterator Begin() const { return ptr_->Begin(); } | ||
ValueIterator End() const { return ptr_->End(); } | ||
GenericArray Reserve(SizeType newCapacity, AllocatorType &allocator) const { ptr_->Reserve(newCapacity, allocator); return *this; } | ||
GenericArray PushBack(ValueType& value, AllocatorType& allocator) const { ptr_->PushBack(value, allocator); return *this; } | ||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS | ||
GenericArray PushBack(ValueType&& value, AllocatorType& allocator) const { ptr_->PushBack(value, allocator); return *this; } | ||
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS | ||
GenericArray PushBack(StringRefType value, AllocatorType& allocator) const { ptr_->PushBack(value, allocator); return *this; } | ||
template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (const GenericArray&)) PushBack(T value, AllocatorType& allocator) const { ptr_->PushBack(value, allocator); return *this; } | ||
GenericArray PopBack() const { ptr_->PopBack(); return *this; } | ||
ValueIterator Erase(ConstValueIterator pos) const { return ptr_->Erase(pos); } | ||
ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) const { return ptr_->Erase(first, last); } | ||
|
||
#if RAPIDJSON_HAS_CXX11_RANGE_FOR | ||
ValueIterator begin() const { return ptr_->Begin(); } | ||
ValueIterator end() const { return ptr_->End(); } | ||
#endif | ||
|
||
private: | ||
GenericArray(ValueType& value) : ptr_(&value) {} | ||
ValueType* ptr_; | ||
}; | ||
|
||
//! Helper class for accessing Value of array type. | ||
/*! | ||
Instance of this helper class is obtained by \c GenericValue::GetArray(). | ||
In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1. | ||
*/ | ||
template <bool Const, typename ValueT> | ||
class GenericObject { | ||
public: | ||
typedef GenericObject<true, ValueT> ConstObject; | ||
typedef GenericObject<false, ValueT> Object; | ||
typedef ValueT PlainType; | ||
typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType; | ||
typedef GenericMemberIterator<Const, typename ValueT::EncodingType, typename ValueT::AllocatorType> MemberIterator; // This may be const or non-const iterator | ||
typedef GenericMemberIterator<true, typename ValueT::EncodingType, typename ValueT::AllocatorType> ConstMemberIterator; | ||
typedef typename ValueType::AllocatorType AllocatorType; | ||
typedef typename ValueType::StringRefType StringRefType; | ||
typedef typename ValueType::EncodingType EncodingType; | ||
typedef typename ValueType::Ch Ch; | ||
|
||
template <typename, typename> | ||
friend class GenericValue; | ||
|
||
GenericObject() : ptr_() {} | ||
GenericObject(const GenericObject& rhs) : ptr_(rhs.ptr_) {} | ||
GenericObject& operator=(const GenericObject& rhs) { ptr_ = rhs.ptr_; return *this; } | ||
~GenericObject() {} | ||
|
||
SizeType MemberCount() const { return ptr_->MemberCount(); } | ||
bool ObjectEmpty() const { return ptr_->ObjectEmpty(); } | ||
template <typename T> ValueType& operator[](T* name) const { return (*ptr_)[name]; } | ||
template <typename SourceAllocator> ValueType& operator[](const GenericValue<EncodingType, SourceAllocator>& name) const { return (*ptr_)[name]; } | ||
#if RAPIDJSON_HAS_STDSTRING | ||
ValueType& operator[](const std::basic_string<Ch>& name) const { return (*ptr_)[name]; } | ||
#endif | ||
MemberIterator MemberBegin() const { return ptr_->MemberBegin(); } | ||
MemberIterator MemberEnd() const { return ptr_->MemberEnd(); } | ||
bool HasMember(const Ch* name) const { return ptr_->HasMember(name); } | ||
#if RAPIDJSON_HAS_STDSTRING | ||
bool HasMember(const std::basic_string<Ch>& name) const { return ptr_->HasMember(name); } | ||
#endif | ||
template <typename SourceAllocator> bool HasMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return ptr_->HasMember(name); } | ||
MemberIterator FindMember(const Ch* name) const { ptr_->FindMember(name); } | ||
template <typename SourceAllocator> MemberIterator FindMember(const GenericValue<EncodingType, SourceAllocator>& name) const { ptr_->FindMember(name); } | ||
#if RAPIDJSON_HAS_STDSTRING | ||
MemberIterator FindMember(const std::basic_string<Ch>& name) const { return ptr_->FindMember(name); } | ||
#endif | ||
GenericObject AddMember(ValueType& name, ValueType& value, AllocatorType& allocator) const { ptr_->AddMember(name, value, allocator); return *this; } | ||
GenericObject AddMember(ValueType& name, StringRefType value, AllocatorType& allocator) const { ptr_->AddMember(name, value, allocator); return *this; } | ||
#if RAPIDJSON_HAS_STDSTRING | ||
GenericObject AddMember(ValueType& name, std::basic_string<Ch>& value, AllocatorType& allocator) const { ptr_->AddMember(name, value, allocator); return *this; } | ||
#endif | ||
template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&)) AddMember(ValueType& name, T value, AllocatorType& allocator) const { ptr_->AddMember(name, value, allocator); return *this; } | ||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS | ||
GenericObject AddMember(ValueType&& name, ValueType&& value, AllocatorType& allocator) const { ptr_->AddMember(name, value, allocator); return *this; } | ||
GenericObject AddMember(ValueType&& name, ValueType& value, AllocatorType& allocator) const { ptr_->AddMember(name, value, allocator); return *this; } | ||
GenericObject AddMember(ValueType& name, ValueType&& value, AllocatorType& allocator) const { ptr_->AddMember(name, value, allocator); return *this; } | ||
GenericObject AddMember(StringRefType name, ValueType&& value, AllocatorType& allocator) const { ptr_->AddMember(name, value, allocator); return *this; } | ||
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS | ||
GenericObject AddMember(StringRefType name, ValueType& value, AllocatorType& allocator) const { ptr_->AddMember(name, value, allocator); return *this; } | ||
GenericObject AddMember(StringRefType name, StringRefType value, AllocatorType& allocator) const { ptr_->AddMember(name, value, allocator); return *this; } | ||
template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericObject)) AddMember(StringRefType name, T value, AllocatorType& allocator) const { ptr_->AddMember(name, value, allocator); return *this; } | ||
void RemoveAllMembers() { return ptr_->RemoveAllMembers(); } | ||
bool RemoveMember(const Ch* name) const { return ptr_->RemoveMember(name); } | ||
#if RAPIDJSON_HAS_STDSTRING | ||
bool RemoveMember(const std::basic_string<Ch>& name) const { return ptr_->RemoveMember(name); } | ||
#endif | ||
template <typename SourceAllocator> bool RemoveMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return ptr_->RemoveMember(name); } | ||
MemberIterator RemoveMember(MemberIterator m) const { return ptr_->RemoveMember(m); } | ||
MemberIterator EraseMember(ConstMemberIterator pos) const { return ptr_->EraseMember(pos); } | ||
MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) const { return ptr_->EraseMember(first, last); } | ||
bool EraseMember(const Ch* name) const { return ptr_->EraseMember(name); } | ||
#if RAPIDJSON_HAS_STDSTRING | ||
bool EraseMember(const std::basic_string<Ch>& name) const { return EraseMember(ValueType(StringRef(name))); } | ||
#endif | ||
template <typename SourceAllocator> bool EraseMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return ptr_->EraseMember(name); } | ||
|
||
#if RAPIDJSON_HAS_CXX11_RANGE_FOR | ||
MemberIterator begin() const { return ptr_->MemberBegin(); } | ||
MemberIterator end() const { return ptr_->MemberEnd(); } | ||
#endif | ||
|
||
private: | ||
GenericObject(ValueType& value) : ptr_(&value) {} | ||
ValueType* ptr_; | ||
}; | ||
|
||
RAPIDJSON_NAMESPACE_END | ||
|
||
#ifdef _MSC_VER | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After this call,
a.ptr_
is null, not an (empty) array. We should add ana.ptr_->SetArray();
here (set for SetObject(Object);` to avoid breaking the invariant.Secondly, we should check for a.ptr_ not being NULL in an assert, which could happen due to a default constructed
Array|Object
instance.