Browse Source

Implement `VariantRefBase` with a CRTP

Benoit Blanchon 3 years ago
parent
commit
0f85a55cac

+ 0 - 1
CHANGELOG.md

@@ -9,7 +9,6 @@ HEAD
 * Fix comparison operators for `JsonArray`, `JsonArrayConst`, `JsonObject`, and `JsonObjectConst`
 * Fix lax parsing of `true`, `false`, and `null` (issue #1781)
 * Remove undocumented `accept()` functions
-* Remove undocumented `ElementProxy` and `MemberProxy` classes
 * Rename `addElement()` to `add()`
 * Remove `getElement()`, `getOrAddElement()`, `getMember()`, and `getOrAddMember()`
 * Remove undocumented `JsonDocument::data()` and `JsonDocument::memoryPool()`

+ 1 - 3
extras/tests/JsonDocument/ElementProxy.cpp

@@ -5,9 +5,7 @@
 #include <ArduinoJson.h>
 #include <catch.hpp>
 
-using namespace ARDUINOJSON_NAMESPACE;
-
-typedef VariantProxy<ElementDataSource<JsonDocument&> > ElementProxy;
+typedef ARDUINOJSON_NAMESPACE::ElementProxy<JsonDocument&> ElementProxy;
 
 TEST_CASE("ElementProxy::add()") {
   DynamicJsonDocument doc(4096);

+ 2 - 3
extras/tests/JsonDocument/MemberProxy.cpp

@@ -5,9 +5,8 @@
 #include <ArduinoJson.h>
 #include <catch.hpp>
 
-using namespace ARDUINOJSON_NAMESPACE;
-
-typedef VariantProxy<MemberDataSource<JsonDocument&, const char*> > MemberProxy;
+typedef ARDUINOJSON_NAMESPACE::MemberProxy<JsonDocument&, const char*>
+    MemberProxy;
 
 TEST_CASE("MemberProxy::add()") {
   DynamicJsonDocument doc(4096);

+ 4 - 5
extras/tests/Misc/TypeTraits.cpp

@@ -184,13 +184,12 @@ TEST_CASE("Polyfills/type_traits") {
     CHECK((is_convertible<VariantRef, JsonVariantConst>::value == true));
     CHECK((is_convertible<VariantConstRef, JsonVariantConst>::value == true));
     CHECK((is_convertible<ArrayRef, JsonVariantConst>::value == true));
-    CHECK((is_convertible<VariantProxy<ElementDataSource<ArrayRef> >,
-                          JsonVariantConst>::value == true));
+    CHECK((is_convertible<ElementProxy<ArrayRef>, JsonVariantConst>::value ==
+           true));
     CHECK((is_convertible<ArrayConstRef, JsonVariantConst>::value == true));
     CHECK((is_convertible<ObjectRef, JsonVariantConst>::value == true));
-    CHECK(
-        (is_convertible<VariantProxy<MemberDataSource<ObjectRef, const char*> >,
-                        JsonVariantConst>::value == true));
+    CHECK((is_convertible<MemberProxy<ObjectRef, const char*>,
+                          JsonVariantConst>::value == true));
     CHECK((is_convertible<ObjectConstRef, JsonVariantConst>::value == true));
     CHECK(
         (is_convertible<DynamicJsonDocument, JsonVariantConst>::value == true));

+ 8 - 9
src/ArduinoJson/Array/ArrayImpl.hpp

@@ -13,21 +13,20 @@ inline ObjectRef ArrayRef::createNestedObject() const {
   return add().to<ObjectRef>();
 }
 
-template <typename TDataSource>
-inline ArrayRef VariantRefBase<TDataSource>::createNestedArray() const {
+template <typename TDerived>
+inline ArrayRef VariantRefBase<TDerived>::createNestedArray() const {
   return add().template to<ArrayRef>();
 }
 
-template <typename TDataSource>
-inline ObjectRef VariantRefBase<TDataSource>::createNestedObject() const {
+template <typename TDerived>
+inline ObjectRef VariantRefBase<TDerived>::createNestedObject() const {
   return add().template to<ObjectRef>();
 }
 
-template <typename TDataSource>
-inline VariantProxy<ElementDataSource<VariantRefBase<TDataSource> > >
-VariantRefBase<TDataSource>::operator[](size_t index) const {
-  return VariantProxy<ElementDataSource<VariantRefBase<TDataSource> > >(
-      ElementDataSource<VariantRefBase<TDataSource> >(*this, index));
+template <typename TDerived>
+inline ElementProxy<TDerived> VariantRefBase<TDerived>::operator[](
+    size_t index) const {
+  return ElementProxy<TDerived>(derived(), index);
 }
 
 }  // namespace ARDUINOJSON_NAMESPACE

+ 2 - 4
src/ArduinoJson/Array/ArrayRef.hpp

@@ -184,10 +184,8 @@ class ArrayRef : public ArrayRefBase<CollectionData>,
   }
 
   // Returns the element at specified index if the variant is an array.
-  FORCE_INLINE VariantProxy<ElementDataSource<ArrayRef> > operator[](
-      size_t index) const {
-    return VariantProxy<ElementDataSource<ArrayRef> >(
-        ElementDataSource<ArrayRef>(*this, index));
+  FORCE_INLINE ElementProxy<ArrayRef> operator[](size_t index) const {
+    return ElementProxy<ArrayRef>(*this, index);
   }
 
   FORCE_INLINE ObjectRef createNestedObject() const;

+ 27 - 9
src/ArduinoJson/Array/ElementProxy.hpp

@@ -4,16 +4,40 @@
 
 #pragma once
 
-#include <ArduinoJson/Variant/VariantProxy.hpp>
+#include <ArduinoJson/Variant/VariantRefBase.hpp>
 
 namespace ARDUINOJSON_NAMESPACE {
 
 template <typename TUpstream>
-class ElementDataSource {
+class ElementProxy : public VariantRefBase<ElementProxy<TUpstream> >,
+                     public VariantOperators<ElementProxy<TUpstream> > {
+  friend class VariantAttorney;
+
  public:
-  ElementDataSource(TUpstream upstream, size_t index)
+  ElementProxy(TUpstream upstream, size_t index)
       : _upstream(upstream), _index(index) {}
 
+  ElementProxy(const ElementProxy& src)
+      : _upstream(src._upstream), _index(src._index) {}
+
+  FORCE_INLINE ElementProxy& operator=(const ElementProxy& src) {
+    this->set(src);
+    return *this;
+  }
+
+  template <typename T>
+  FORCE_INLINE ElementProxy& operator=(const T& src) {
+    this->set(src);
+    return *this;
+  }
+
+  template <typename T>
+  FORCE_INLINE ElementProxy& operator=(T* src) {
+    this->set(src);
+    return *this;
+  }
+
+ private:
   FORCE_INLINE MemoryPool* getPool() const {
     return VariantAttorney::getPool(_upstream);
   }
@@ -27,12 +51,6 @@ class ElementDataSource {
                                   _index, VariantAttorney::getPool(_upstream));
   }
 
- private:
-#if defined _MSC_VER && _MSC_VER <= 1800  // Visual Studio 2013 or below
-  // Prevent "assignment operator could not be generated"
-  ElementDataSource& operator=(const ElementDataSource&);
-#endif
-
   TUpstream _upstream;
   size_t _index;
 };

+ 8 - 14
src/ArduinoJson/Document/JsonDocument.hpp

@@ -139,24 +139,20 @@ class JsonDocument : public VariantOperators<const JsonDocument&> {
   // operator[](const std::string&)
   // operator[](const String&)
   template <typename TString>
-  FORCE_INLINE typename enable_if<
-      IsString<TString>::value,
-      VariantProxy<MemberDataSource<JsonDocument&, TString> > >::type
+  FORCE_INLINE typename enable_if<IsString<TString>::value,
+                                  MemberProxy<JsonDocument&, TString> >::type
   operator[](const TString& key) {
-    return VariantProxy<MemberDataSource<JsonDocument&, TString> >(
-        MemberDataSource<JsonDocument&, TString>(*this, key));
+    return MemberProxy<JsonDocument&, TString>(*this, key);
   }
 
   // operator[](char*)
   // operator[](const char*)
   // operator[](const __FlashStringHelper*)
   template <typename TChar>
-  FORCE_INLINE typename enable_if<
-      IsString<TChar*>::value,
-      VariantProxy<MemberDataSource<JsonDocument&, TChar*> > >::type
+  FORCE_INLINE typename enable_if<IsString<TChar*>::value,
+                                  MemberProxy<JsonDocument&, TChar*> >::type
   operator[](TChar* key) {
-    return VariantProxy<MemberDataSource<JsonDocument&, TChar*> >(
-        MemberDataSource<JsonDocument&, TChar*>(*this, key));
+    return MemberProxy<JsonDocument&, TChar*>(*this, key);
   }
 
   // operator[](const std::string&) const
@@ -178,10 +174,8 @@ class JsonDocument : public VariantOperators<const JsonDocument&> {
     return VariantConstRef(_data.getMember(adaptString(key)));
   }
 
-  FORCE_INLINE VariantProxy<ElementDataSource<JsonDocument&> > operator[](
-      size_t index) {
-    return VariantProxy<ElementDataSource<JsonDocument&> >(
-        ElementDataSource<JsonDocument&>(*this, index));
+  FORCE_INLINE ElementProxy<JsonDocument&> operator[](size_t index) {
+    return ElementProxy<JsonDocument&>(*this, index);
   }
 
   FORCE_INLINE VariantConstRef operator[](size_t index) const {

+ 28 - 8
src/ArduinoJson/Object/MemberProxy.hpp

@@ -4,16 +4,41 @@
 
 #pragma once
 
-#include <ArduinoJson/Variant/VariantProxy.hpp>
+#include <ArduinoJson/Variant/VariantRefBase.hpp>
 
 namespace ARDUINOJSON_NAMESPACE {
 
 template <typename TUpstream, typename TStringRef>
-class MemberDataSource {
+class MemberProxy
+    : public VariantRefBase<MemberProxy<TUpstream, TStringRef> >,
+      public VariantOperators<MemberProxy<TUpstream, TStringRef> > {
+  friend class VariantAttorney;
+
  public:
-  FORCE_INLINE MemberDataSource(TUpstream upstream, TStringRef key)
+  FORCE_INLINE MemberProxy(TUpstream upstream, TStringRef key)
       : _upstream(upstream), _key(key) {}
 
+  MemberProxy(const MemberProxy& src)
+      : _upstream(src._upstream), _key(src._key) {}
+
+  FORCE_INLINE MemberProxy& operator=(const MemberProxy& src) {
+    this->set(src);
+    return *this;
+  }
+
+  template <typename T>
+  FORCE_INLINE MemberProxy& operator=(const T& src) {
+    this->set(src);
+    return *this;
+  }
+
+  template <typename T>
+  FORCE_INLINE MemberProxy& operator=(T* src) {
+    this->set(src);
+    return *this;
+  }
+
+ private:
   FORCE_INLINE MemoryPool* getPool() const {
     return VariantAttorney::getPool(_upstream);
   }
@@ -30,11 +55,6 @@ class MemberDataSource {
   }
 
  private:
-#if defined _MSC_VER && _MSC_VER <= 1800  // Visual Studio 2013 or below
-  // Prevent "assignment operator could not be generated"
-  MemberDataSource& operator=(const MemberDataSource&);
-#endif
-
   TUpstream _upstream;
   TStringRef _key;
 };

+ 24 - 29
src/ArduinoJson/Object/ObjectImpl.hpp

@@ -19,68 +19,63 @@ inline ArrayRef ObjectRef::createNestedArray(TChar* key) const {
   return operator[](key).template to<ArrayRef>();
 }
 
-template <typename TDataSource>
+template <typename TDerived>
 template <typename TString>
-inline ArrayRef VariantRefBase<TDataSource>::createNestedArray(
+inline ArrayRef VariantRefBase<TDerived>::createNestedArray(
     const TString& key) const {
   return operator[](key).template to<ArrayRef>();
 }
 
-template <typename TDataSource>
+template <typename TDerived>
 template <typename TChar>
-inline ArrayRef VariantRefBase<TDataSource>::createNestedArray(
-    TChar* key) const {
+inline ArrayRef VariantRefBase<TDerived>::createNestedArray(TChar* key) const {
   return operator[](key).template to<ArrayRef>();
 }
 
-template <typename TDataSource>
+template <typename TDerived>
 template <typename TString>
-inline ObjectRef VariantRefBase<TDataSource>::createNestedObject(
+inline ObjectRef VariantRefBase<TDerived>::createNestedObject(
     const TString& key) const {
   return operator[](key).template to<ObjectRef>();
 }
 
-template <typename TDataSource>
+template <typename TDerived>
 template <typename TChar>
-inline ObjectRef VariantRefBase<TDataSource>::createNestedObject(
+inline ObjectRef VariantRefBase<TDerived>::createNestedObject(
     TChar* key) const {
   return operator[](key).template to<ObjectRef>();
 }
 
-template <typename TDataSource>
+template <typename TDerived>
 template <typename TString>
 inline typename enable_if<IsString<TString>::value, bool>::type
-VariantRefBase<TDataSource>::containsKey(const TString& key) const {
-  return variantGetMember(VariantAttorney::getData(*this), adaptString(key)) !=
-         0;
+VariantRefBase<TDerived>::containsKey(const TString& key) const {
+  return variantGetMember(VariantAttorney::getData(derived()),
+                          adaptString(key)) != 0;
 }
 
-template <typename TDataSource>
+template <typename TDerived>
 template <typename TChar>
 inline typename enable_if<IsString<TChar*>::value, bool>::type
-VariantRefBase<TDataSource>::containsKey(TChar* key) const {
-  return variantGetMember(VariantAttorney::getData(*this), adaptString(key)) !=
-         0;
+VariantRefBase<TDerived>::containsKey(TChar* key) const {
+  return variantGetMember(VariantAttorney::getData(derived()),
+                          adaptString(key)) != 0;
 }
 
-template <typename TDataSource>
+template <typename TDerived>
 template <typename TString>
 inline typename enable_if<IsString<TString*>::value,
-                          VariantProxy<MemberDataSource<
-                              VariantRefBase<TDataSource>, TString*> > >::type
-VariantRefBase<TDataSource>::operator[](TString* key) const {
-  return VariantProxy<MemberDataSource<VariantRefBase, TString*> >(
-      MemberDataSource<VariantRefBase, TString*>(*this, key));
+                          MemberProxy<TDerived, TString*> >::type
+VariantRefBase<TDerived>::operator[](TString* key) const {
+  return MemberProxy<TDerived, TString*>(derived(), key);
 }
 
-template <typename TDataSource>
+template <typename TDerived>
 template <typename TString>
 inline typename enable_if<IsString<TString>::value,
-                          VariantProxy<MemberDataSource<
-                              VariantRefBase<TDataSource>, TString> > >::type
-VariantRefBase<TDataSource>::operator[](const TString& key) const {
-  return VariantProxy<MemberDataSource<VariantRefBase, TString> >(
-      MemberDataSource<VariantRefBase, TString>(*this, key));
+                          MemberProxy<TDerived, TString> >::type
+VariantRefBase<TDerived>::operator[](const TString& key) const {
+  return MemberProxy<TDerived, TString>(derived(), key);
 }
 
 }  // namespace ARDUINOJSON_NAMESPACE

+ 6 - 10
src/ArduinoJson/Object/ObjectRef.hpp

@@ -176,21 +176,17 @@ class ObjectRef : public ObjectRefBase<CollectionData>,
   }
 
   template <typename TString>
-  FORCE_INLINE typename enable_if<
-      IsString<TString>::value,
-      VariantProxy<MemberDataSource<ObjectRef, TString> > >::type
+  FORCE_INLINE typename enable_if<IsString<TString>::value,
+                                  MemberProxy<ObjectRef, TString> >::type
   operator[](const TString& key) const {
-    return VariantProxy<MemberDataSource<ObjectRef, TString> >(
-        MemberDataSource<ObjectRef, TString>(*this, key));
+    return MemberProxy<ObjectRef, TString>(*this, key);
   }
 
   template <typename TChar>
-  FORCE_INLINE typename enable_if<
-      IsString<TChar*>::value,
-      VariantProxy<MemberDataSource<ObjectRef, TChar*> > >::type
+  FORCE_INLINE typename enable_if<IsString<TChar*>::value,
+                                  MemberProxy<ObjectRef, TChar*> >::type
   operator[](TChar* key) const {
-    return VariantProxy<MemberDataSource<ObjectRef, TChar*> >(
-        MemberDataSource<ObjectRef, TChar*>(*this, key));
+    return MemberProxy<ObjectRef, TChar*>(*this, key);
   }
 
   FORCE_INLINE void remove(iterator it) const {

+ 16 - 17
src/ArduinoJson/Variant/VariantImpl.hpp

@@ -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>());
 }
 

+ 0 - 51
src/ArduinoJson/Variant/VariantProxy.hpp

@@ -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

+ 7 - 14
src/ArduinoJson/Variant/VariantRef.hpp

@@ -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) {

+ 20 - 22
src/ArduinoJson/Variant/VariantRefBase.hpp

@@ -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