Implement VariantRefBase with a CRTP

This commit is contained in:
Benoit Blanchon
2022-11-26 18:34:25 +01:00
parent 21db92af47
commit 0f85a55cac
15 changed files with 153 additions and 199 deletions

View File

@@ -104,52 +104,51 @@ inline bool VariantData::copyFrom(const VariantData& src, MemoryPool* pool) {
}
}
template <typename TSource>
inline VariantRef VariantRefBase<TSource>::add() const {
template <typename TDerived>
inline VariantRef VariantRefBase<TDerived>::add() const {
return VariantRef(getPool(), variantAddElement(getOrCreateData(), getPool()));
}
template <typename TSource>
inline VariantRef VariantRefBase<TSource>::getVariant() const {
template <typename TDerived>
inline VariantRef VariantRefBase<TDerived>::getVariant() const {
return VariantRef(getPool(), getData());
}
template <typename TSource>
inline VariantRef VariantRefBase<TSource>::getOrCreateVariant() const {
template <typename TDerived>
inline VariantRef VariantRefBase<TDerived>::getOrCreateVariant() const {
return VariantRef(getPool(), getOrCreateData());
}
template <typename TSource>
template <typename TDerived>
template <typename T>
inline typename enable_if<is_same<T, ArrayRef>::value, ArrayRef>::type
VariantRefBase<TSource>::to() const {
VariantRefBase<TDerived>::to() const {
return ArrayRef(getPool(), variantToArray(getOrCreateData()));
}
template <typename TSource>
template <typename TDerived>
template <typename T>
typename enable_if<is_same<T, ObjectRef>::value, ObjectRef>::type
VariantRefBase<TSource>::to() const {
VariantRefBase<TDerived>::to() const {
return ObjectRef(getPool(), variantToObject(getOrCreateData()));
}
template <typename TSource>
template <typename TDerived>
template <typename T>
typename enable_if<is_same<T, VariantRef>::value, VariantRef>::type
VariantRefBase<TSource>::to() const {
VariantRefBase<TDerived>::to() const {
variantSetNull(getOrCreateData());
return *this;
}
// Out of class definition to avoid #1560
template <typename TSource>
inline bool VariantRefBase<TSource>::set(char value) const {
template <typename TDerived>
inline bool VariantRefBase<TDerived>::set(char value) const {
return set(static_cast<signed char>(value));
}
template <typename TDataSource>
inline void convertToJson(const VariantRefBase<TDataSource>& src,
VariantRef dst) {
template <typename TDerived>
inline void convertToJson(const VariantRefBase<TDerived>& src, VariantRef dst) {
dst.set(src.template as<VariantConstRef>());
}

View File

@@ -1,51 +0,0 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2022, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Variant/VariantOperators.hpp>
#include <ArduinoJson/Variant/VariantRefBase.hpp>
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable : 4522)
#endif
namespace ARDUINOJSON_NAMESPACE {
template <typename TDataSource>
class VariantProxy : public VariantRefBase<TDataSource>,
public VariantOperators<VariantProxy<TDataSource> > {
public:
explicit FORCE_INLINE VariantProxy(TDataSource source)
: VariantRefBase<TDataSource>(source) {}
// Copy-constructor required because of user-defined copy-assignment
// operator
FORCE_INLINE VariantProxy(const VariantProxy& src)
: VariantRefBase<TDataSource>(src) {}
FORCE_INLINE VariantProxy& operator=(const VariantProxy& src) {
this->set(src);
return *this;
}
template <typename T>
FORCE_INLINE VariantProxy& operator=(const T& src) {
this->set(src);
return *this;
}
template <typename T>
FORCE_INLINE VariantProxy& operator=(T* src) {
this->set(src);
return *this;
}
};
} // namespace ARDUINOJSON_NAMESPACE
#ifdef _MSC_VER
# pragma warning(pop)
#endif

View File

@@ -8,13 +8,16 @@
namespace ARDUINOJSON_NAMESPACE {
class VariantDataSource {
class VariantRef : public VariantRefBase<VariantRef>,
public VariantOperators<VariantRef> {
friend class VariantAttorney;
public:
VariantDataSource() : _data(0), _pool(0) {}
VariantRef() : _data(0), _pool(0) {}
VariantDataSource(MemoryPool* pool, VariantData* data)
: _data(data), _pool(pool) {}
VariantRef(MemoryPool* pool, VariantData* data) : _data(data), _pool(pool) {}
private:
FORCE_INLINE MemoryPool* getPool() const {
return _pool;
}
@@ -27,20 +30,10 @@ class VariantDataSource {
return _data;
}
private:
VariantData* _data;
MemoryPool* _pool;
};
class VariantRef : public VariantRefBase<VariantDataSource>,
public VariantOperators<VariantRef> {
public:
VariantRef() : VariantRefBase<VariantDataSource>(VariantDataSource()) {}
VariantRef(MemoryPool* pool, VariantData* data)
: VariantRefBase<VariantDataSource>(VariantDataSource(pool, data)) {}
};
template <>
struct Converter<VariantRef> : private VariantAttorney {
static void toJson(VariantRef src, VariantRef dst) {

View File

@@ -15,21 +15,16 @@ namespace ARDUINOJSON_NAMESPACE {
class VariantRef;
template <typename>
class ElementDataSource;
class ElementProxy;
template <typename, typename>
class MemberDataSource;
class MemberProxy;
template <typename>
class VariantProxy;
template <typename TDataSource>
template <typename TDerived>
class VariantRefBase : public VariantTag {
friend class VariantAttorney;
public:
explicit FORCE_INLINE VariantRefBase(TDataSource source) : _source(source) {}
FORCE_INLINE void clear() const {
variantSetNull(getData());
}
@@ -206,8 +201,7 @@ class VariantRefBase : public VariantTag {
FORCE_INLINE ArrayRef createNestedArray() const;
FORCE_INLINE ObjectRef createNestedObject() const;
FORCE_INLINE VariantProxy<ElementDataSource<VariantRefBase> > operator[](
size_t index) const;
FORCE_INLINE ElementProxy<TDerived> operator[](size_t index) const;
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value, bool>::type
@@ -218,15 +212,13 @@ class VariantRefBase : public VariantTag {
containsKey(TChar* key) const;
template <typename TString>
FORCE_INLINE typename enable_if<
IsString<TString>::value,
VariantProxy<MemberDataSource<VariantRefBase, TString> > >::type
FORCE_INLINE typename enable_if<IsString<TString>::value,
MemberProxy<TDerived, TString> >::type
operator[](const TString& key) const;
template <typename TChar>
FORCE_INLINE typename enable_if<
IsString<TChar*>::value,
VariantProxy<MemberDataSource<VariantRefBase, TChar*> > >::type
FORCE_INLINE typename enable_if<IsString<TChar*>::value,
MemberProxy<TDerived, TChar*> >::type
operator[](TChar* key) const;
template <typename TString>
@@ -241,17 +233,25 @@ class VariantRefBase : public VariantTag {
template <typename TChar>
ObjectRef createNestedObject(TChar* key) const;
protected:
private:
TDerived& derived() {
return static_cast<TDerived&>(*this);
}
const TDerived& derived() const {
return static_cast<const TDerived&>(*this);
}
FORCE_INLINE MemoryPool* getPool() const {
return _source.getPool();
return VariantAttorney::getPool(derived());
}
FORCE_INLINE VariantData* getData() const {
return _source.getData();
return VariantAttorney::getData(derived());
}
FORCE_INLINE VariantData* getOrCreateData() const {
return _source.getOrCreateData();
return VariantAttorney::getOrCreateData(derived());
}
private:
@@ -262,8 +262,6 @@ class VariantRefBase : public VariantTag {
}
FORCE_INLINE VariantRef getOrCreateVariant() const;
TDataSource _source;
};
} // namespace ARDUINOJSON_NAMESPACE