Move public facing SFINAEs to template declarations

This commit is contained in:
Benoit Blanchon
2024-12-23 17:44:52 +01:00
parent e33e78d202
commit de05814294
20 changed files with 311 additions and 304 deletions

View File

@ -10,6 +10,7 @@ HEAD
* `JsonString` is now stored by copy, unless specified otherwise * `JsonString` is now stored by copy, unless specified otherwise
* Replace undocumented `JsonString::Ownership` with `bool` * Replace undocumented `JsonString::Ownership` with `bool`
* Rename undocumented `JsonString::isLinked()` to `isStatic()` * Rename undocumented `JsonString::isLinked()` to `isStatic()`
* Move public facing SFINAEs to template declarations
> ### BREAKING CHANGES > ### BREAKING CHANGES
> >

View File

@ -43,16 +43,18 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
// Appends a new (empty) element to the array. // Appends a new (empty) element to the array.
// Returns a reference to the new element. // Returns a reference to the new element.
// https://arduinojson.org/v7/api/jsonarray/add/ // https://arduinojson.org/v7/api/jsonarray/add/
template <typename T> template <typename T, detail::enable_if_t<
detail::enable_if_t<!detail::is_same<T, JsonVariant>::value, T> add() const { !detail::is_same<T, JsonVariant>::value, int> = 0>
T add() const {
return add<JsonVariant>().to<T>(); return add<JsonVariant>().to<T>();
} }
// Appends a new (null) element to the array. // Appends a new (null) element to the array.
// Returns a reference to the new element. // Returns a reference to the new element.
// https://arduinojson.org/v7/api/jsonarray/add/ // https://arduinojson.org/v7/api/jsonarray/add/
template <typename T> template <typename T, detail::enable_if_t<
detail::enable_if_t<detail::is_same<T, JsonVariant>::value, T> add() const { detail::is_same<T, JsonVariant>::value, int> = 0>
JsonVariant add() const {
return JsonVariant(detail::ArrayData::addElement(data_, resources_), return JsonVariant(detail::ArrayData::addElement(data_, resources_),
resources_); resources_);
} }
@ -67,7 +69,7 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
// Appends a value to the array. // Appends a value to the array.
// https://arduinojson.org/v7/api/jsonarray/add/ // https://arduinojson.org/v7/api/jsonarray/add/
template <typename T, template <typename T,
typename = detail::enable_if_t<!detail::is_const<T>::value>> detail::enable_if_t<!detail::is_const<T>::value, int> = 0>
bool add(T* value) const { bool add(T* value) const {
return detail::ArrayData::addValue(data_, value, resources_); return detail::ArrayData::addValue(data_, value, resources_);
} }
@ -115,9 +117,9 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
// Removes the element at the specified index. // Removes the element at the specified index.
// https://arduinojson.org/v7/api/jsonarray/remove/ // https://arduinojson.org/v7/api/jsonarray/remove/
template <typename TVariant> template <typename TVariant,
detail::enable_if_t<detail::IsVariant<TVariant>::value> remove( detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
const TVariant& variant) const { void remove(const TVariant& variant) const {
if (variant.template is<size_t>()) if (variant.template is<size_t>())
remove(variant.template as<size_t>()); remove(variant.template as<size_t>());
} }
@ -130,19 +132,17 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
// Gets or sets the element at the specified index. // Gets or sets the element at the specified index.
// https://arduinojson.org/v7/api/jsonarray/subscript/ // https://arduinojson.org/v7/api/jsonarray/subscript/
template <typename T> template <typename T,
detail::enable_if_t<detail::is_integral<T>::value, detail::enable_if_t<detail::is_integral<T>::value, int> = 0>
detail::ElementProxy<JsonArray>> detail::ElementProxy<JsonArray> operator[](T index) const {
operator[](T index) const {
return {*this, size_t(index)}; return {*this, size_t(index)};
} }
// Gets or sets the element at the specified index. // Gets or sets the element at the specified index.
// https://arduinojson.org/v7/api/jsonarray/subscript/ // https://arduinojson.org/v7/api/jsonarray/subscript/
template <typename TVariant> template <typename TVariant,
detail::enable_if_t<detail::IsVariant<TVariant>::value, detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
detail::ElementProxy<JsonArray>> detail::ElementProxy<JsonArray> operator[](const TVariant& variant) const {
operator[](const TVariant& variant) const {
if (variant.template is<size_t>()) if (variant.template is<size_t>())
return {*this, variant.template as<size_t>()}; return {*this, variant.template as<size_t>()};
else else

View File

@ -45,9 +45,9 @@ class JsonArrayConst : public detail::VariantOperators<JsonArrayConst> {
// Returns the element at the specified index. // Returns the element at the specified index.
// https://arduinojson.org/v7/api/jsonarrayconst/subscript/ // https://arduinojson.org/v7/api/jsonarrayconst/subscript/
template <typename T> template <typename T,
detail::enable_if_t<detail::is_integral<T>::value, JsonVariantConst> detail::enable_if_t<detail::is_integral<T>::value, int> = 0>
operator[](T index) const { JsonVariantConst operator[](T index) const {
return JsonVariantConst( return JsonVariantConst(
detail::ArrayData::getElement(data_, size_t(index), resources_), detail::ArrayData::getElement(data_, size_t(index), resources_),
resources_); resources_);
@ -55,9 +55,9 @@ class JsonArrayConst : public detail::VariantOperators<JsonArrayConst> {
// Returns the element at the specified index. // Returns the element at the specified index.
// https://arduinojson.org/v7/api/jsonarrayconst/subscript/ // https://arduinojson.org/v7/api/jsonarrayconst/subscript/
template <typename TVariant> template <typename TVariant,
detail::enable_if_t<detail::IsVariant<TVariant>::value, JsonVariantConst> detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
operator[](const TVariant& variant) const { JsonVariantConst operator[](const TVariant& variant) const {
if (variant.template is<size_t>()) if (variant.template is<size_t>())
return operator[](variant.template as<size_t>()); return operator[](variant.template as<size_t>());
else else

View File

@ -11,27 +11,26 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
// Copies a value to a JsonVariant. // Copies a value to a JsonVariant.
// This is a degenerated form of copyArray() to stop the recursion. // This is a degenerated form of copyArray() to stop the recursion.
template <typename T> template <typename T, detail::enable_if_t<!detail::is_array<T>::value, int> = 0>
inline detail::enable_if_t<!detail::is_array<T>::value, bool> copyArray( inline bool copyArray(const T& src, JsonVariant dst) {
const T& src, JsonVariant dst) {
return dst.set(src); return dst.set(src);
} }
// Copies values from an array to a JsonArray or a JsonVariant. // Copies values from an array to a JsonArray or a JsonVariant.
// https://arduinojson.org/v7/api/misc/copyarray/ // https://arduinojson.org/v7/api/misc/copyarray/
template <typename T, size_t N, typename TDestination> template <typename T, size_t N, typename TDestination,
inline detail::enable_if_t< detail::enable_if_t<
!detail::is_base_of<JsonDocument, TDestination>::value, bool> !detail::is_base_of<JsonDocument, TDestination>::value, int> = 0>
copyArray(T (&src)[N], const TDestination& dst) { inline bool copyArray(T (&src)[N], const TDestination& dst) {
return copyArray(src, N, dst); return copyArray(src, N, dst);
} }
// Copies values from an array to a JsonArray or a JsonVariant. // Copies values from an array to a JsonArray or a JsonVariant.
// https://arduinojson.org/v7/api/misc/copyarray/ // https://arduinojson.org/v7/api/misc/copyarray/
template <typename T, typename TDestination> template <typename T, typename TDestination,
inline detail::enable_if_t< detail::enable_if_t<
!detail::is_base_of<JsonDocument, TDestination>::value, bool> !detail::is_base_of<JsonDocument, TDestination>::value, int> = 0>
copyArray(const T* src, size_t len, const TDestination& dst) { inline bool copyArray(const T* src, size_t len, const TDestination& dst) {
bool ok = true; bool ok = true;
for (size_t i = 0; i < len; i++) { for (size_t i = 0; i < len; i++) {
ok &= copyArray(src[i], dst.template add<JsonVariant>()); ok &= copyArray(src[i], dst.template add<JsonVariant>());
@ -62,9 +61,8 @@ inline bool copyArray(const T* src, size_t len, JsonDocument& dst) {
// Copies a value from a JsonVariant. // Copies a value from a JsonVariant.
// This is a degenerated form of copyArray() to stop the recursion. // This is a degenerated form of copyArray() to stop the recursion.
template <typename T> template <typename T, detail::enable_if_t<!detail::is_array<T>::value, int> = 0>
inline detail::enable_if_t<!detail::is_array<T>::value, size_t> copyArray( inline size_t copyArray(JsonVariantConst src, T& dst) {
JsonVariantConst src, T& dst) {
dst = src.as<T>(); dst = src.as<T>();
return 1; return 1;
} }
@ -102,11 +100,12 @@ inline size_t copyArray(JsonVariantConst src, char (&dst)[N]) {
// Copies values from a JsonDocument to an array. // Copies values from a JsonDocument to an array.
// https://arduinojson.org/v7/api/misc/copyarray/ // https://arduinojson.org/v7/api/misc/copyarray/
template <typename TSource, typename T> template <
inline detail::enable_if_t<detail::is_array<T>::value && typename TSource, typename T,
detail::is_base_of<JsonDocument, TSource>::value, detail::enable_if_t<detail::is_array<T>::value &&
size_t> detail::is_base_of<JsonDocument, TSource>::value,
copyArray(const TSource& src, T& dst) { int> = 0>
inline size_t copyArray(const TSource& src, T& dst) {
return copyArray(src.template as<JsonArrayConst>(), dst); return copyArray(src.template as<JsonArrayConst>(), dst);
} }

View File

@ -55,10 +55,11 @@ DeserializationError doDeserialize(TDestination&& dst, TReader reader,
return err; return err;
} }
template <template <typename> class TDeserializer, typename TDestination, template <
typename TStream, typename... Args, template <typename> class TDeserializer, typename TDestination,
typename = enable_if_t< // issue #1897 typename TStream, typename... Args,
!is_integral<typename first_or_void<Args...>::type>::value>> enable_if_t< // issue #1897
!is_integral<typename first_or_void<Args...>::type>::value, int> = 0>
DeserializationError deserialize(TDestination&& dst, TStream&& input, DeserializationError deserialize(TDestination&& dst, TStream&& input,
Args... args) { Args... args) {
return doDeserialize<TDeserializer>( return doDeserialize<TDeserializer>(
@ -68,7 +69,7 @@ DeserializationError deserialize(TDestination&& dst, TStream&& input,
template <template <typename> class TDeserializer, typename TDestination, template <template <typename> class TDeserializer, typename TDestination,
typename TChar, typename Size, typename... Args, typename TChar, typename Size, typename... Args,
typename = enable_if_t<is_integral<Size>::value>> enable_if_t<is_integral<Size>::value, int> = 0>
DeserializationError deserialize(TDestination&& dst, TChar* input, DeserializationError deserialize(TDestination&& dst, TChar* input,
Size inputSize, Args... args) { Size inputSize, Args... args) {
return doDeserialize<TDeserializer>(dst, makeReader(input, size_t(inputSize)), return doDeserialize<TDeserializer>(dst, makeReader(input, size_t(inputSize)),

View File

@ -36,14 +36,15 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
} }
// Construct from variant, array, or object // Construct from variant, array, or object
template <typename T> template <typename T,
JsonDocument( detail::enable_if_t<detail::IsVariant<T>::value ||
const T& src, Allocator* alloc = detail::DefaultAllocator::instance(), detail::is_same<T, JsonArray>::value ||
detail::enable_if_t<detail::IsVariant<T>::value || detail::is_same<T, JsonArrayConst>::value ||
detail::is_same<T, JsonArray>::value || detail::is_same<T, JsonObject>::value ||
detail::is_same<T, JsonArrayConst>::value || detail::is_same<T, JsonObjectConst>::value,
detail::is_same<T, JsonObject>::value || int> = 0>
detail::is_same<T, JsonObjectConst>::value>* = 0) JsonDocument(const T& src,
Allocator* alloc = detail::DefaultAllocator::instance())
: JsonDocument(alloc) { : JsonDocument(alloc) {
set(src); set(src);
} }
@ -136,16 +137,17 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
// Replaces the root with the specified value. // Replaces the root with the specified value.
// https://arduinojson.org/v7/api/jsondocument/set/ // https://arduinojson.org/v7/api/jsondocument/set/
template <typename T> template <
detail::enable_if_t<!detail::is_base_of<JsonDocument, T>::value, bool> set( typename T,
const T& src) { detail::enable_if_t<!detail::is_base_of<JsonDocument, T>::value, int> = 0>
bool set(const T& src) {
return to<JsonVariant>().set(src); return to<JsonVariant>().set(src);
} }
// Replaces the root with the specified value. // Replaces the root with the specified value.
// https://arduinojson.org/v7/api/jsondocument/set/ // https://arduinojson.org/v7/api/jsondocument/set/
template <typename TChar, template <typename TChar,
typename = detail::enable_if_t<!detail::is_const<TChar>::value>> detail::enable_if_t<!detail::is_const<TChar>::value, int> = 0>
bool set(TChar* src) { bool set(TChar* src) {
return to<JsonVariant>().set(src); return to<JsonVariant>().set(src);
} }
@ -168,68 +170,67 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
// DEPRECATED: use obj[key].is<T>() instead // DEPRECATED: use obj[key].is<T>() instead
// https://arduinojson.org/v7/api/jsondocument/containskey/ // https://arduinojson.org/v7/api/jsondocument/containskey/
template <typename TString> template <typename TString,
detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
ARDUINOJSON_DEPRECATED("use doc[key].is<T>() instead") ARDUINOJSON_DEPRECATED("use doc[key].is<T>() instead")
detail::enable_if_t<detail::IsString<TString>::value, bool> containsKey( bool containsKey(const TString& key) const {
const TString& key) const {
return data_.getMember(detail::adaptString(key), &resources_) != 0; return data_.getMember(detail::adaptString(key), &resources_) != 0;
} }
// DEPRECATED: use obj[key].is<T>() instead // DEPRECATED: use obj[key].is<T>() instead
// https://arduinojson.org/v7/api/jsondocument/containskey/ // https://arduinojson.org/v7/api/jsondocument/containskey/
template <typename TVariant> template <typename TVariant,
detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
ARDUINOJSON_DEPRECATED("use doc[key].is<T>() instead") ARDUINOJSON_DEPRECATED("use doc[key].is<T>() instead")
detail::enable_if_t<detail::IsVariant<TVariant>::value, bool> containsKey( bool containsKey(const TVariant& key) const {
const TVariant& key) const {
return containsKey(key.template as<const char*>()); return containsKey(key.template as<const char*>());
} }
// Gets or sets a root object's member. // Gets or sets a root object's member.
// https://arduinojson.org/v7/api/jsondocument/subscript/ // https://arduinojson.org/v7/api/jsondocument/subscript/
template <typename TString> template <typename TString,
detail::enable_if_t< detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
detail::IsString<TString>::value, detail::MemberProxy<JsonDocument&, detail::AdaptedString<TString>> operator[](
detail::MemberProxy<JsonDocument&, detail::AdaptedString<TString>>> const TString& key) {
operator[](const TString& key) {
return {*this, detail::adaptString(key)}; return {*this, detail::adaptString(key)};
} }
// Gets or sets a root object's member. // Gets or sets a root object's member.
// https://arduinojson.org/v7/api/jsondocument/subscript/ // https://arduinojson.org/v7/api/jsondocument/subscript/
template <typename TChar> template <typename TChar,
detail::enable_if_t< detail::enable_if_t<detail::IsString<TChar*>::value &&
detail::IsString<TChar*>::value && !detail::is_const<TChar>::value, !detail::is_const<TChar>::value,
detail::MemberProxy<JsonDocument&, detail::AdaptedString<TChar*>>> int> = 0>
operator[](TChar* key) { detail::MemberProxy<JsonDocument&, detail::AdaptedString<TChar*>> operator[](
TChar* key) {
return {*this, detail::adaptString(key)}; return {*this, detail::adaptString(key)};
} }
// Gets a root object's member. // Gets a root object's member.
// https://arduinojson.org/v7/api/jsondocument/subscript/ // https://arduinojson.org/v7/api/jsondocument/subscript/
template <typename TString> template <typename TString,
detail::enable_if_t<detail::IsString<TString>::value, JsonVariantConst> detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
operator[](const TString& key) const { JsonVariantConst operator[](const TString& key) const {
return JsonVariantConst( return JsonVariantConst(
data_.getMember(detail::adaptString(key), &resources_), &resources_); data_.getMember(detail::adaptString(key), &resources_), &resources_);
} }
// Gets a root object's member. // Gets a root object's member.
// https://arduinojson.org/v7/api/jsondocument/subscript/ // https://arduinojson.org/v7/api/jsondocument/subscript/
template <typename TChar> template <typename TChar,
detail::enable_if_t<detail::IsString<TChar*>::value && detail::enable_if_t<detail::IsString<TChar*>::value &&
!detail::is_const<TChar>::value, !detail::is_const<TChar>::value,
JsonVariantConst> int> = 0>
operator[](TChar* key) const { JsonVariantConst operator[](TChar* key) const {
return JsonVariantConst( return JsonVariantConst(
data_.getMember(detail::adaptString(key), &resources_), &resources_); data_.getMember(detail::adaptString(key), &resources_), &resources_);
} }
// Gets or sets a root array's element. // Gets or sets a root array's element.
// https://arduinojson.org/v7/api/jsondocument/subscript/ // https://arduinojson.org/v7/api/jsondocument/subscript/
template <typename T> template <typename T,
detail::enable_if_t<detail::is_integral<T>::value, detail::enable_if_t<detail::is_integral<T>::value, int> = 0>
detail::ElementProxy<JsonDocument&>> detail::ElementProxy<JsonDocument&> operator[](T index) {
operator[](T index) {
return {*this, size_t(index)}; return {*this, size_t(index)};
} }
@ -241,9 +242,9 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
// Gets or sets a root object's member. // Gets or sets a root object's member.
// https://arduinojson.org/v7/api/jsondocument/subscript/ // https://arduinojson.org/v7/api/jsondocument/subscript/
template <typename TVariant> template <typename TVariant,
detail::enable_if_t<detail::IsVariant<TVariant>::value, JsonVariantConst> detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
operator[](const TVariant& key) const { JsonVariantConst operator[](const TVariant& key) const {
if (key.template is<JsonString>()) if (key.template is<JsonString>())
return operator[](key.template as<JsonString>()); return operator[](key.template as<JsonString>());
if (key.template is<size_t>()) if (key.template is<size_t>())
@ -254,16 +255,18 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
// Appends a new (empty) element to the root array. // Appends a new (empty) element to the root array.
// Returns a reference to the new element. // Returns a reference to the new element.
// https://arduinojson.org/v7/api/jsondocument/add/ // https://arduinojson.org/v7/api/jsondocument/add/
template <typename T> template <typename T, detail::enable_if_t<
detail::enable_if_t<!detail::is_same<T, JsonVariant>::value, T> add() { !detail::is_same<T, JsonVariant>::value, int> = 0>
T add() {
return add<JsonVariant>().to<T>(); return add<JsonVariant>().to<T>();
} }
// Appends a new (null) element to the root array. // Appends a new (null) element to the root array.
// Returns a reference to the new element. // Returns a reference to the new element.
// https://arduinojson.org/v7/api/jsondocument/add/ // https://arduinojson.org/v7/api/jsondocument/add/
template <typename T> template <typename T, detail::enable_if_t<
detail::enable_if_t<detail::is_same<T, JsonVariant>::value, T> add() { detail::is_same<T, JsonVariant>::value, int> = 0>
JsonVariant add() {
return JsonVariant(data_.addElement(&resources_), &resources_); return JsonVariant(data_.addElement(&resources_), &resources_);
} }
@ -277,43 +280,45 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
// Appends a value to the root array. // Appends a value to the root array.
// https://arduinojson.org/v7/api/jsondocument/add/ // https://arduinojson.org/v7/api/jsondocument/add/
template <typename TChar, template <typename TChar,
typename = detail::enable_if_t<!detail::is_const<TChar>::value>> detail::enable_if_t<!detail::is_const<TChar>::value, int> = 0>
bool add(TChar* value) { bool add(TChar* value) {
return data_.addValue(value, &resources_); return data_.addValue(value, &resources_);
} }
// Removes an element of the root array. // Removes an element of the root array.
// https://arduinojson.org/v7/api/jsondocument/remove/ // https://arduinojson.org/v7/api/jsondocument/remove/
template <typename T> template <typename T,
detail::enable_if_t<detail::is_integral<T>::value> remove(T index) { detail::enable_if_t<detail::is_integral<T>::value, int> = 0>
void remove(T index) {
detail::VariantData::removeElement(getData(), size_t(index), detail::VariantData::removeElement(getData(), size_t(index),
getResourceManager()); getResourceManager());
} }
// Removes a member of the root object. // Removes a member of the root object.
// https://arduinojson.org/v7/api/jsondocument/remove/ // https://arduinojson.org/v7/api/jsondocument/remove/
template <typename TChar> template <typename TChar,
detail::enable_if_t<detail::IsString<TChar*>::value && detail::enable_if_t<detail::IsString<TChar*>::value &&
!detail::is_const<TChar>::value> !detail::is_const<TChar>::value,
remove(TChar* key) { int> = 0>
void remove(TChar* key) {
detail::VariantData::removeMember(getData(), detail::adaptString(key), detail::VariantData::removeMember(getData(), detail::adaptString(key),
getResourceManager()); getResourceManager());
} }
// Removes a member of the root object. // Removes a member of the root object.
// https://arduinojson.org/v7/api/jsondocument/remove/ // https://arduinojson.org/v7/api/jsondocument/remove/
template <typename TString> template <typename TString,
detail::enable_if_t<detail::IsString<TString>::value> remove( detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
const TString& key) { void remove(const TString& key) {
detail::VariantData::removeMember(getData(), detail::adaptString(key), detail::VariantData::removeMember(getData(), detail::adaptString(key),
getResourceManager()); getResourceManager());
} }
// Removes a member of the root object or an element of the root array. // Removes a member of the root object or an element of the root array.
// https://arduinojson.org/v7/api/jsondocument/remove/ // https://arduinojson.org/v7/api/jsondocument/remove/
template <typename TVariant> template <typename TVariant,
detail::enable_if_t<detail::IsVariant<TVariant>::value> remove( detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
const TVariant& key) { void remove(const TVariant& key) {
if (key.template is<const char*>()) if (key.template is<const char*>())
remove(key.template as<const char*>()); remove(key.template as<const char*>());
if (key.template is<size_t>()) if (key.template is<size_t>())

View File

@ -697,10 +697,11 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
// Parses a JSON input, filters, and puts the result in a JsonDocument. // Parses a JSON input, filters, and puts the result in a JsonDocument.
// https://arduinojson.org/v7/api/json/deserializejson/ // https://arduinojson.org/v7/api/json/deserializejson/
template <typename TDestination, typename... Args> template <typename TDestination, typename... Args,
detail::enable_if_t<detail::is_deserialize_destination<TDestination>::value, detail::enable_if_t<
DeserializationError> detail::is_deserialize_destination<TDestination>::value, int> = 0>
deserializeJson(TDestination&& dst, Args&&... args) { inline DeserializationError deserializeJson(TDestination&& dst,
Args&&... args) {
using namespace detail; using namespace detail;
return deserialize<JsonDeserializer>(detail::forward<TDestination>(dst), return deserialize<JsonDeserializer>(detail::forward<TDestination>(dst),
detail::forward<Args>(args)...); detail::forward<Args>(args)...);
@ -708,10 +709,11 @@ deserializeJson(TDestination&& dst, Args&&... args) {
// Parses a JSON input, filters, and puts the result in a JsonDocument. // Parses a JSON input, filters, and puts the result in a JsonDocument.
// https://arduinojson.org/v7/api/json/deserializejson/ // https://arduinojson.org/v7/api/json/deserializejson/
template <typename TDestination, typename TChar, typename... Args> template <typename TDestination, typename TChar, typename... Args,
detail::enable_if_t<detail::is_deserialize_destination<TDestination>::value, detail::enable_if_t<
DeserializationError> detail::is_deserialize_destination<TDestination>::value, int> = 0>
deserializeJson(TDestination&& dst, TChar* input, Args&&... args) { inline DeserializationError deserializeJson(TDestination&& dst, TChar* input,
Args&&... args) {
using namespace detail; using namespace detail;
return deserialize<JsonDeserializer>(detail::forward<TDestination>(dst), return deserialize<JsonDeserializer>(detail::forward<TDestination>(dst),
input, detail::forward<Args>(args)...); input, detail::forward<Args>(args)...);

View File

@ -129,9 +129,10 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
// Produces a minified JSON document. // Produces a minified JSON document.
// https://arduinojson.org/v7/api/json/serializejson/ // https://arduinojson.org/v7/api/json/serializejson/
template <typename TDestination> template <
detail::enable_if_t<!detail::is_pointer<TDestination>::value, size_t> typename TDestination,
serializeJson(JsonVariantConst source, TDestination& destination) { detail::enable_if_t<!detail::is_pointer<TDestination>::value, int> = 0>
size_t serializeJson(JsonVariantConst source, TDestination& destination) {
using namespace detail; using namespace detail;
return serialize<JsonSerializer>(source, destination); return serialize<JsonSerializer>(source, destination);
} }
@ -152,10 +153,10 @@ inline size_t measureJson(JsonVariantConst source) {
} }
#if ARDUINOJSON_ENABLE_STD_STREAM #if ARDUINOJSON_ENABLE_STD_STREAM
template <typename T> template <typename T,
inline detail::enable_if_t<detail::is_convertible<T, JsonVariantConst>::value, detail::enable_if_t<
std::ostream&> detail::is_convertible<T, JsonVariantConst>::value, int> = 0>
operator<<(std::ostream& os, const T& source) { inline std::ostream& operator<<(std::ostream& os, const T& source) {
serializeJson(source, os); serializeJson(source, os);
return os; return os;
} }

View File

@ -83,9 +83,11 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
// Produces JsonDocument to create a prettified JSON document. // Produces JsonDocument to create a prettified JSON document.
// https://arduinojson.org/v7/api/json/serializejsonpretty/ // https://arduinojson.org/v7/api/json/serializejsonpretty/
template <typename TDestination> template <
detail::enable_if_t<!detail::is_pointer<TDestination>::value, size_t> typename TDestination,
serializeJsonPretty(JsonVariantConst source, TDestination& destination) { detail::enable_if_t<!detail::is_pointer<TDestination>::value, int> = 0>
inline size_t serializeJsonPretty(JsonVariantConst source,
TDestination& destination) {
using namespace ArduinoJson::detail; using namespace ArduinoJson::detail;
return serialize<PrettyJsonSerializer>(source, destination); return serialize<PrettyJsonSerializer>(source, destination);
} }

View File

@ -464,10 +464,11 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
// Parses a MessagePack input and puts the result in a JsonDocument. // Parses a MessagePack input and puts the result in a JsonDocument.
// https://arduinojson.org/v7/api/msgpack/deserializemsgpack/ // https://arduinojson.org/v7/api/msgpack/deserializemsgpack/
template <typename TDestination, typename... Args> template <typename TDestination, typename... Args,
detail::enable_if_t<detail::is_deserialize_destination<TDestination>::value, detail::enable_if_t<
DeserializationError> detail::is_deserialize_destination<TDestination>::value, int> = 0>
deserializeMsgPack(TDestination&& dst, Args&&... args) { inline DeserializationError deserializeMsgPack(TDestination&& dst,
Args&&... args) {
using namespace detail; using namespace detail;
return deserialize<MsgPackDeserializer>(detail::forward<TDestination>(dst), return deserialize<MsgPackDeserializer>(detail::forward<TDestination>(dst),
detail::forward<Args>(args)...); detail::forward<Args>(args)...);
@ -475,10 +476,11 @@ deserializeMsgPack(TDestination&& dst, Args&&... args) {
// Parses a MessagePack input and puts the result in a JsonDocument. // Parses a MessagePack input and puts the result in a JsonDocument.
// https://arduinojson.org/v7/api/msgpack/deserializemsgpack/ // https://arduinojson.org/v7/api/msgpack/deserializemsgpack/
template <typename TDestination, typename TChar, typename... Args> template <typename TDestination, typename TChar, typename... Args,
detail::enable_if_t<detail::is_deserialize_destination<TDestination>::value, detail::enable_if_t<
DeserializationError> detail::is_deserialize_destination<TDestination>::value, int> = 0>
deserializeMsgPack(TDestination&& dst, TChar* input, Args&&... args) { inline DeserializationError deserializeMsgPack(TDestination&& dst, TChar* input,
Args&&... args) {
using namespace detail; using namespace detail;
return deserialize<MsgPackDeserializer>(detail::forward<TDestination>(dst), return deserialize<MsgPackDeserializer>(detail::forward<TDestination>(dst),
input, input,

View File

@ -218,9 +218,10 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
// Produces a MessagePack document. // Produces a MessagePack document.
// https://arduinojson.org/v7/api/msgpack/serializemsgpack/ // https://arduinojson.org/v7/api/msgpack/serializemsgpack/
template <typename TDestination> template <
detail::enable_if_t<!detail::is_pointer<TDestination>::value, size_t> typename TDestination,
serializeMsgPack(JsonVariantConst source, TDestination& output) { detail::enable_if_t<!detail::is_pointer<TDestination>::value, int> = 0>
inline size_t serializeMsgPack(JsonVariantConst source, TDestination& output) {
using namespace ArduinoJson::detail; using namespace ArduinoJson::detail;
return serialize<MsgPackSerializer>(source, output); return serialize<MsgPackSerializer>(source, output);
} }

View File

@ -101,31 +101,30 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
// Gets or sets the member with specified key. // Gets or sets the member with specified key.
// https://arduinojson.org/v7/api/jsonobject/subscript/ // https://arduinojson.org/v7/api/jsonobject/subscript/
template <typename TString> template <typename TString,
detail::enable_if_t< detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
detail::IsString<TString>::value, detail::MemberProxy<JsonObject, detail::AdaptedString<TString>> operator[](
detail::MemberProxy<JsonObject, detail::AdaptedString<TString>>> const TString& key) const {
operator[](const TString& key) const {
return {*this, detail::adaptString(key)}; return {*this, detail::adaptString(key)};
} }
// Gets or sets the member with specified key. // Gets or sets the member with specified key.
// https://arduinojson.org/v7/api/jsonobject/subscript/ // https://arduinojson.org/v7/api/jsonobject/subscript/
template <typename TChar> template <typename TChar,
detail::enable_if_t< detail::enable_if_t<detail::IsString<TChar*>::value &&
detail::IsString<TChar*>::value && !detail::is_const<TChar>::value, !detail::is_const<TChar>::value,
detail::MemberProxy<JsonObject, detail::AdaptedString<TChar*>>> int> = 0>
operator[](TChar* key) const { detail::MemberProxy<JsonObject, detail::AdaptedString<TChar*>> operator[](
TChar* key) const {
return {*this, detail::adaptString(key)}; return {*this, detail::adaptString(key)};
} }
// Gets or sets the member with specified key. // Gets or sets the member with specified key.
// https://arduinojson.org/v7/api/jsonobject/subscript/ // https://arduinojson.org/v7/api/jsonobject/subscript/
template <typename TVariant> template <typename TVariant,
detail::enable_if_t< detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
detail::IsVariant<TVariant>::value, detail::MemberProxy<JsonObject, detail::AdaptedString<JsonString>> operator[](
detail::MemberProxy<JsonObject, detail::AdaptedString<JsonString>>> const TVariant& key) const {
operator[](const TVariant& key) const {
return {*this, detail::adaptString(key.template as<JsonString>())}; return {*this, detail::adaptString(key.template as<JsonString>())};
} }
@ -137,18 +136,18 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
// Removes the member with the specified key. // Removes the member with the specified key.
// https://arduinojson.org/v7/api/jsonobject/remove/ // https://arduinojson.org/v7/api/jsonobject/remove/
template <typename TString> template <typename TString,
detail::enable_if_t<detail::IsString<TString>::value> remove( detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
const TString& key) const { void remove(const TString& key) const {
detail::ObjectData::removeMember(data_, detail::adaptString(key), detail::ObjectData::removeMember(data_, detail::adaptString(key),
resources_); resources_);
} }
// Removes the member with the specified key. // Removes the member with the specified key.
// https://arduinojson.org/v7/api/jsonobject/remove/ // https://arduinojson.org/v7/api/jsonobject/remove/
template <typename TVariant> template <typename TVariant,
detail::enable_if_t<detail::IsVariant<TVariant>::value> remove( detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
const TVariant& key) const { void remove(const TVariant& key) const {
if (key.template is<const char*>()) if (key.template is<const char*>())
remove(key.template as<const char*>()); remove(key.template as<const char*>());
} }
@ -163,31 +162,32 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
// DEPRECATED: use obj[key].is<T>() instead // DEPRECATED: use obj[key].is<T>() instead
// https://arduinojson.org/v7/api/jsonobject/containskey/ // https://arduinojson.org/v7/api/jsonobject/containskey/
template <typename TString> template <typename TString,
detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
ARDUINOJSON_DEPRECATED("use obj[key].is<T>() instead") ARDUINOJSON_DEPRECATED("use obj[key].is<T>() instead")
detail::enable_if_t<detail::IsString<TString>::value, bool> containsKey( bool containsKey(const TString& key) const {
const TString& key) const {
return detail::ObjectData::getMember(data_, detail::adaptString(key), return detail::ObjectData::getMember(data_, detail::adaptString(key),
resources_) != 0; resources_) != 0;
} }
// DEPRECATED: use obj["key"].is<T>() instead // DEPRECATED: use obj["key"].is<T>() instead
// https://arduinojson.org/v7/api/jsonobject/containskey/ // https://arduinojson.org/v7/api/jsonobject/containskey/
template <typename TChar> template <typename TChar,
detail::enable_if_t<detail::IsString<TChar*>::value &&
!detail::is_const<TChar>::value,
int> = 0>
ARDUINOJSON_DEPRECATED("use obj[\"key\"].is<T>() instead") ARDUINOJSON_DEPRECATED("use obj[\"key\"].is<T>() instead")
detail::enable_if_t<detail::IsString<TChar*>::value && bool containsKey(TChar* key) const {
!detail::is_const<TChar>::value,
bool> containsKey(TChar* key) const {
return detail::ObjectData::getMember(data_, detail::adaptString(key), return detail::ObjectData::getMember(data_, detail::adaptString(key),
resources_) != 0; resources_) != 0;
} }
// DEPRECATED: use obj[key].is<T>() instead // DEPRECATED: use obj[key].is<T>() instead
// https://arduinojson.org/v7/api/jsonobject/containskey/ // https://arduinojson.org/v7/api/jsonobject/containskey/
template <typename TVariant> template <typename TVariant,
detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
ARDUINOJSON_DEPRECATED("use obj[key].is<T>() instead") ARDUINOJSON_DEPRECATED("use obj[key].is<T>() instead")
detail::enable_if_t<detail::IsVariant<TVariant>::value, bool> containsKey( bool containsKey(const TVariant& key) const {
const TVariant& key) const {
return containsKey(key.template as<const char*>()); return containsKey(key.template as<const char*>());
} }

View File

@ -70,10 +70,10 @@ class JsonObjectConst : public detail::VariantOperators<JsonObjectConst> {
// DEPRECATED: use obj[key].is<T>() instead // DEPRECATED: use obj[key].is<T>() instead
// https://arduinojson.org/v7/api/jsonobjectconst/containskey/ // https://arduinojson.org/v7/api/jsonobjectconst/containskey/
template <typename TString> template <typename TString,
detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
ARDUINOJSON_DEPRECATED("use obj[key].is<T>() instead") ARDUINOJSON_DEPRECATED("use obj[key].is<T>() instead")
detail::enable_if_t<detail::IsString<TString>::value, bool> containsKey( bool containsKey(const TString& key) const {
const TString& key) const {
return detail::ObjectData::getMember(data_, detail::adaptString(key), return detail::ObjectData::getMember(data_, detail::adaptString(key),
resources_) != 0; resources_) != 0;
} }
@ -89,18 +89,18 @@ class JsonObjectConst : public detail::VariantOperators<JsonObjectConst> {
// DEPRECATED: use obj[key].is<T>() instead // DEPRECATED: use obj[key].is<T>() instead
// https://arduinojson.org/v7/api/jsonobjectconst/containskey/ // https://arduinojson.org/v7/api/jsonobjectconst/containskey/
template <typename TVariant> template <typename TVariant,
detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
ARDUINOJSON_DEPRECATED("use obj[key].is<T>() instead") ARDUINOJSON_DEPRECATED("use obj[key].is<T>() instead")
detail::enable_if_t<detail::IsVariant<TVariant>::value, bool> containsKey( bool containsKey(const TVariant& key) const {
const TVariant& key) const {
return containsKey(key.template as<const char*>()); return containsKey(key.template as<const char*>());
} }
// Gets the member with specified key. // Gets the member with specified key.
// https://arduinojson.org/v7/api/jsonobjectconst/subscript/ // https://arduinojson.org/v7/api/jsonobjectconst/subscript/
template <typename TString> template <typename TString,
detail::enable_if_t<detail::IsString<TString>::value, JsonVariantConst> detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
operator[](const TString& key) const { JsonVariantConst operator[](const TString& key) const {
return JsonVariantConst(detail::ObjectData::getMember( return JsonVariantConst(detail::ObjectData::getMember(
data_, detail::adaptString(key), resources_), data_, detail::adaptString(key), resources_),
resources_); resources_);
@ -108,11 +108,11 @@ class JsonObjectConst : public detail::VariantOperators<JsonObjectConst> {
// Gets the member with specified key. // Gets the member with specified key.
// https://arduinojson.org/v7/api/jsonobjectconst/subscript/ // https://arduinojson.org/v7/api/jsonobjectconst/subscript/
template <typename TChar> template <typename TChar,
detail::enable_if_t<detail::IsString<TChar*>::value && detail::enable_if_t<detail::IsString<TChar*>::value &&
!detail::is_const<TChar>::value, !detail::is_const<TChar>::value,
JsonVariantConst> int> = 0>
operator[](TChar* key) const { JsonVariantConst operator[](TChar* key) const {
return JsonVariantConst(detail::ObjectData::getMember( return JsonVariantConst(detail::ObjectData::getMember(
data_, detail::adaptString(key), resources_), data_, detail::adaptString(key), resources_),
resources_); resources_);
@ -120,9 +120,9 @@ class JsonObjectConst : public detail::VariantOperators<JsonObjectConst> {
// Gets the member with specified key. // Gets the member with specified key.
// https://arduinojson.org/v7/api/jsonobjectconst/subscript/ // https://arduinojson.org/v7/api/jsonobjectconst/subscript/
template <typename TVariant> template <typename TVariant,
detail::enable_if_t<detail::IsVariant<TVariant>::value, JsonVariantConst> detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
operator[](const TVariant& key) const { JsonVariantConst operator[](const TVariant& key) const {
if (key.template is<JsonString>()) if (key.template is<JsonString>())
return operator[](key.template as<JsonString>()); return operator[](key.template as<JsonString>());
else else

View File

@ -39,7 +39,7 @@ class MemberProxy
return *this; return *this;
} }
template <typename T, typename = enable_if_t<!is_const<T>::value>> template <typename T, enable_if_t<!is_const<T>::value, int> = 0>
MemberProxy& operator=(T* src) { MemberProxy& operator=(T* src) {
this->set(src); this->set(src);
return *this; return *this;

View File

@ -24,9 +24,10 @@ class JsonString {
JsonString(const char* data, bool isStatic = false) JsonString(const char* data, bool isStatic = false)
: str_(data, data ? ::strlen(data) : 0, isStatic) {} : str_(data, data ? ::strlen(data) : 0, isStatic) {}
template <typename TSize, typename = detail::enable_if_t< template <typename TSize,
detail::is_integral<TSize>::value && detail::enable_if_t<detail::is_integral<TSize>::value &&
!detail::is_same<TSize, bool>::value>> !detail::is_same<TSize, bool>::value,
int> = 0>
JsonString(const char* data, TSize sz, bool isStatic = false) JsonString(const char* data, TSize sz, bool isStatic = false)
: str_(data, size_t(sz), isStatic) {} : str_(data, size_t(sz), isStatic) {}

View File

@ -34,7 +34,7 @@ AdaptedString<TString> adaptString(TString&& s) {
return StringAdapterFor<TString>::adapt(detail::forward<TString>(s)); return StringAdapterFor<TString>::adapt(detail::forward<TString>(s));
} }
template <typename TChar, typename = enable_if_t<!is_const<TChar>::value>> template <typename TChar, enable_if_t<!is_const<TChar>::value, int> = 0>
AdaptedString<TChar*> adaptString(TChar* p) { AdaptedString<TChar*> adaptString(TChar* p) {
return StringAdapter<TChar*>::adapt(p); return StringAdapter<TChar*>::adapt(p);
} }

View File

@ -68,27 +68,29 @@ class JsonVariantConst : public detail::VariantTag,
// Casts the value to the specified type. // Casts the value to the specified type.
// https://arduinojson.org/v7/api/jsonvariantconst/as/ // https://arduinojson.org/v7/api/jsonvariantconst/as/
template <typename T, template <typename T,
detail::enable_if_t<ConversionSupported<T>::value, bool> = true> detail::enable_if_t<ConversionSupported<T>::value, int> = 0>
T as() const { T as() const {
return Converter<T>::fromJson(*this); return Converter<T>::fromJson(*this);
} }
// Invalid conversion. Will not compile. // Invalid conversion. Will not compile.
template <typename T, template <typename T,
detail::enable_if_t<!ConversionSupported<T>::value, bool> = true> detail::enable_if_t<!ConversionSupported<T>::value, int> = 0>
detail::InvalidConversion<JsonVariantConst, T> as() const; detail::InvalidConversion<JsonVariantConst, T> as() const;
// Returns true if the value is of the specified type. // Returns true if the value is of the specified type.
// https://arduinojson.org/v7/api/jsonvariantconst/is/ // https://arduinojson.org/v7/api/jsonvariantconst/is/
template <typename T> template <typename T,
detail::enable_if_t<ConversionSupported<T>::value, bool> is() const { detail::enable_if_t<ConversionSupported<T>::value, int> = 0>
bool is() const {
return Converter<T>::checkJson(*this); return Converter<T>::checkJson(*this);
} }
// Always returns false for the unsupported types. // Always returns false for the unsupported types.
// https://arduinojson.org/v7/api/jsonvariantconst/is/ // https://arduinojson.org/v7/api/jsonvariantconst/is/
template <typename T> template <typename T,
detail::enable_if_t<!ConversionSupported<T>::value, bool> is() const { detail::enable_if_t<!ConversionSupported<T>::value, int> = 0>
bool is() const {
return false; return false;
} }
@ -99,9 +101,9 @@ class JsonVariantConst : public detail::VariantTag,
// Gets array's element at specified index. // Gets array's element at specified index.
// https://arduinojson.org/v7/api/jsonvariantconst/subscript/ // https://arduinojson.org/v7/api/jsonvariantconst/subscript/
template <typename T> template <typename T,
detail::enable_if_t<detail::is_integral<T>::value, JsonVariantConst> detail::enable_if_t<detail::is_integral<T>::value, int> = 0>
operator[](T index) const { JsonVariantConst operator[](T index) const {
return JsonVariantConst( return JsonVariantConst(
detail::VariantData::getElement(data_, size_t(index), resources_), detail::VariantData::getElement(data_, size_t(index), resources_),
resources_); resources_);
@ -109,9 +111,9 @@ class JsonVariantConst : public detail::VariantTag,
// Gets object's member with specified key. // Gets object's member with specified key.
// https://arduinojson.org/v7/api/jsonvariantconst/subscript/ // https://arduinojson.org/v7/api/jsonvariantconst/subscript/
template <typename TString> template <typename TString,
detail::enable_if_t<detail::IsString<TString>::value, JsonVariantConst> detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
operator[](const TString& key) const { JsonVariantConst operator[](const TString& key) const {
return JsonVariantConst(detail::VariantData::getMember( return JsonVariantConst(detail::VariantData::getMember(
data_, detail::adaptString(key), resources_), data_, detail::adaptString(key), resources_),
resources_); resources_);
@ -119,11 +121,11 @@ class JsonVariantConst : public detail::VariantTag,
// Gets object's member with specified key. // Gets object's member with specified key.
// https://arduinojson.org/v7/api/jsonvariantconst/subscript/ // https://arduinojson.org/v7/api/jsonvariantconst/subscript/
template <typename TChar> template <typename TChar,
detail::enable_if_t<detail::IsString<TChar*>::value && detail::enable_if_t<detail::IsString<TChar*>::value &&
!detail::is_const<TChar>::value, !detail::is_const<TChar>::value,
JsonVariantConst> int> = 0>
operator[](TChar* key) const { JsonVariantConst operator[](TChar* key) const {
return JsonVariantConst(detail::VariantData::getMember( return JsonVariantConst(detail::VariantData::getMember(
data_, detail::adaptString(key), resources_), data_, detail::adaptString(key), resources_),
resources_); resources_);
@ -132,9 +134,9 @@ class JsonVariantConst : public detail::VariantTag,
// Gets object's member with specified key or the array's element at the // Gets object's member with specified key or the array's element at the
// specified index. // specified index.
// https://arduinojson.org/v7/api/jsonvariantconst/subscript/ // https://arduinojson.org/v7/api/jsonvariantconst/subscript/
template <typename TVariant> template <typename TVariant,
detail::enable_if_t<detail::IsVariant<TVariant>::value, JsonVariantConst> detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
operator[](const TVariant& key) const { JsonVariantConst operator[](const TVariant& key) const {
if (key.template is<size_t>()) if (key.template is<size_t>())
return operator[](key.template as<size_t>()); return operator[](key.template as<size_t>());
else else
@ -143,31 +145,32 @@ class JsonVariantConst : public detail::VariantTag,
// DEPRECATED: use obj[key].is<T>() instead // DEPRECATED: use obj[key].is<T>() instead
// https://arduinojson.org/v7/api/jsonvariantconst/containskey/ // https://arduinojson.org/v7/api/jsonvariantconst/containskey/
template <typename TString> template <typename TString,
detail::enable_if_t<detail::IsString<TString>::value, int> = 0>
ARDUINOJSON_DEPRECATED("use var[key].is<T>() instead") ARDUINOJSON_DEPRECATED("use var[key].is<T>() instead")
detail::enable_if_t<detail::IsString<TString>::value, bool> containsKey( bool containsKey(const TString& key) const {
const TString& key) const {
return detail::VariantData::getMember(getData(), detail::adaptString(key), return detail::VariantData::getMember(getData(), detail::adaptString(key),
resources_) != 0; resources_) != 0;
} }
// DEPRECATED: use obj["key"].is<T>() instead // DEPRECATED: use obj["key"].is<T>() instead
// https://arduinojson.org/v7/api/jsonvariantconst/containskey/ // https://arduinojson.org/v7/api/jsonvariantconst/containskey/
template <typename TChar> template <typename TChar,
detail::enable_if_t<detail::IsString<TChar*>::value &&
!detail::is_const<TChar>::value,
int> = 0>
ARDUINOJSON_DEPRECATED("use obj[\"key\"].is<T>() instead") ARDUINOJSON_DEPRECATED("use obj[\"key\"].is<T>() instead")
detail::enable_if_t<detail::IsString<TChar*>::value && bool containsKey(TChar* key) const {
!detail::is_const<TChar>::value,
bool> containsKey(TChar* key) const {
return detail::VariantData::getMember(getData(), detail::adaptString(key), return detail::VariantData::getMember(getData(), detail::adaptString(key),
resources_) != 0; resources_) != 0;
} }
// DEPRECATED: use obj[key].is<T>() instead // DEPRECATED: use obj[key].is<T>() instead
// https://arduinojson.org/v7/api/jsonvariantconst/containskey/ // https://arduinojson.org/v7/api/jsonvariantconst/containskey/
template <typename TVariant> template <typename TVariant,
detail::enable_if_t<detail::IsVariant<TVariant>::value, int> = 0>
ARDUINOJSON_DEPRECATED("use var[key].is<T>() instead") ARDUINOJSON_DEPRECATED("use var[key].is<T>() instead")
detail::enable_if_t<detail::IsVariant<TVariant>::value, bool> containsKey( bool containsKey(const TVariant& key) const {
const TVariant& key) const {
return containsKey(key.template as<const char*>()); return containsKey(key.template as<const char*>());
} }

View File

@ -30,9 +30,9 @@ struct VariantOperators : VariantOperatorTag {
// int operator|(JsonVariant, int) // int operator|(JsonVariant, int)
// float operator|(JsonVariant, float) // float operator|(JsonVariant, float)
// bool operator|(JsonVariant, bool) // bool operator|(JsonVariant, bool)
template <typename T> template <typename T,
friend enable_if_t<!IsVariant<T>::value && !is_array<T>::value, T> operator|( enable_if_t<!IsVariant<T>::value && !is_array<T>::value, int> = 0>
const TVariant& variant, const T& defaultValue) { friend T operator|(const TVariant& variant, const T& defaultValue) {
if (variant.template is<T>()) if (variant.template is<T>())
return variant.template as<T>(); return variant.template as<T>();
else else
@ -73,9 +73,9 @@ struct VariantOperators : VariantOperatorTag {
friend bool operator==(const TVariant& lhs, T* rhs) { friend bool operator==(const TVariant& lhs, T* rhs) {
return compare(lhs, rhs) == COMPARE_RESULT_EQUAL; return compare(lhs, rhs) == COMPARE_RESULT_EQUAL;
} }
template <typename T> template <typename T,
friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, bool> enable_if_t<!is_base_of<VariantOperatorTag, T>::value, int> = 0>
operator==(const TVariant& lhs, const T& rhs) { friend bool operator==(const TVariant& lhs, const T& rhs) {
return compare(lhs, rhs) == COMPARE_RESULT_EQUAL; return compare(lhs, rhs) == COMPARE_RESULT_EQUAL;
} }
@ -94,9 +94,9 @@ struct VariantOperators : VariantOperatorTag {
friend bool operator!=(const TVariant& lhs, T* rhs) { friend bool operator!=(const TVariant& lhs, T* rhs) {
return compare(lhs, rhs) != COMPARE_RESULT_EQUAL; return compare(lhs, rhs) != COMPARE_RESULT_EQUAL;
} }
template <typename T> template <typename T,
friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, bool> enable_if_t<!is_base_of<VariantOperatorTag, T>::value, int> = 0>
operator!=(TVariant lhs, const T& rhs) { friend bool operator!=(TVariant lhs, const T& rhs) {
return compare(lhs, rhs) != COMPARE_RESULT_EQUAL; return compare(lhs, rhs) != COMPARE_RESULT_EQUAL;
} }
@ -115,9 +115,9 @@ struct VariantOperators : VariantOperatorTag {
friend bool operator<(const TVariant& lhs, T* rhs) { friend bool operator<(const TVariant& lhs, T* rhs) {
return compare(lhs, rhs) == COMPARE_RESULT_LESS; return compare(lhs, rhs) == COMPARE_RESULT_LESS;
} }
template <typename T> template <typename T,
friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, bool> operator<( enable_if_t<!is_base_of<VariantOperatorTag, T>::value, int> = 0>
TVariant lhs, const T& rhs) { friend bool operator<(TVariant lhs, const T& rhs) {
return compare(lhs, rhs) == COMPARE_RESULT_LESS; return compare(lhs, rhs) == COMPARE_RESULT_LESS;
} }
@ -136,9 +136,9 @@ struct VariantOperators : VariantOperatorTag {
friend bool operator<=(const TVariant& lhs, T* rhs) { friend bool operator<=(const TVariant& lhs, T* rhs) {
return (compare(lhs, rhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0; return (compare(lhs, rhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
} }
template <typename T> template <typename T,
friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, bool> enable_if_t<!is_base_of<VariantOperatorTag, T>::value, int> = 0>
operator<=(TVariant lhs, const T& rhs) { friend bool operator<=(TVariant lhs, const T& rhs) {
return (compare(lhs, rhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0; return (compare(lhs, rhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
} }
@ -157,9 +157,9 @@ struct VariantOperators : VariantOperatorTag {
friend bool operator>(const TVariant& lhs, T* rhs) { friend bool operator>(const TVariant& lhs, T* rhs) {
return compare(lhs, rhs) == COMPARE_RESULT_GREATER; return compare(lhs, rhs) == COMPARE_RESULT_GREATER;
} }
template <typename T> template <typename T,
friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, bool> operator>( enable_if_t<!is_base_of<VariantOperatorTag, T>::value, int> = 0>
TVariant lhs, const T& rhs) { friend bool operator>(TVariant lhs, const T& rhs) {
return compare(lhs, rhs) == COMPARE_RESULT_GREATER; return compare(lhs, rhs) == COMPARE_RESULT_GREATER;
} }
@ -178,9 +178,9 @@ struct VariantOperators : VariantOperatorTag {
friend bool operator>=(const TVariant& lhs, T* rhs) { friend bool operator>=(const TVariant& lhs, T* rhs) {
return (compare(lhs, rhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0; return (compare(lhs, rhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
} }
template <typename T> template <typename T,
friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, bool> enable_if_t<!is_base_of<VariantOperatorTag, T>::value, int> = 0>
operator>=(const TVariant& lhs, const T& rhs) { friend bool operator>=(const TVariant& lhs, const T& rhs) {
return (compare(lhs, rhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0; return (compare(lhs, rhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
} }
}; };

View File

@ -48,25 +48,25 @@ class VariantRefBase : public VariantTag {
template <typename T> template <typename T>
T as() const; T as() const;
template <typename T, typename = enable_if_t<!is_same<T, TDerived>::value>> template <typename T, enable_if_t<!is_same<T, TDerived>::value, int> = 0>
operator T() const { operator T() const {
return as<T>(); return as<T>();
} }
// Sets the value to an empty array. // Sets the value to an empty array.
// https://arduinojson.org/v7/api/jsonvariant/to/ // https://arduinojson.org/v7/api/jsonvariant/to/
template <typename T> template <typename T, enable_if_t<is_same<T, JsonArray>::value, int> = 0>
enable_if_t<is_same<T, JsonArray>::value, JsonArray> to() const; JsonArray to() const;
// Sets the value to an empty object. // Sets the value to an empty object.
// https://arduinojson.org/v7/api/jsonvariant/to/ // https://arduinojson.org/v7/api/jsonvariant/to/
template <typename T> template <typename T, enable_if_t<is_same<T, JsonObject>::value, int> = 0>
enable_if_t<is_same<T, JsonObject>::value, JsonObject> to() const; JsonObject to() const;
// Sets the value to null. // Sets the value to null.
// https://arduinojson.org/v7/api/jsonvariant/to/ // https://arduinojson.org/v7/api/jsonvariant/to/
template <typename T> template <typename T, enable_if_t<is_same<T, JsonVariant>::value, int> = 0>
enable_if_t<is_same<T, JsonVariant>::value, JsonVariant> to() const; JsonVariant to() const;
// Returns true if the value is of the specified type. // Returns true if the value is of the specified type.
// https://arduinojson.org/v7/api/jsonvariant/is/ // https://arduinojson.org/v7/api/jsonvariant/is/
@ -85,7 +85,7 @@ class VariantRefBase : public VariantTag {
// Copies the specified value. // Copies the specified value.
// https://arduinojson.org/v7/api/jsonvariant/set/ // https://arduinojson.org/v7/api/jsonvariant/set/
template <typename T, template <typename T,
typename = detail::enable_if_t<!detail::is_const<T>::value>> detail::enable_if_t<!detail::is_const<T>::value, int> = 0>
bool set(T* value) const { bool set(T* value) const {
return doSet<Converter<T*>>(value); return doSet<Converter<T*>>(value);
} }
@ -105,16 +105,16 @@ class VariantRefBase : public VariantTag {
// Appends a new (empty) element to the array. // Appends a new (empty) element to the array.
// Returns a reference to the new element. // Returns a reference to the new element.
// https://arduinojson.org/v7/api/jsonvariant/add/ // https://arduinojson.org/v7/api/jsonvariant/add/
template <typename T> template <typename T, enable_if_t<!is_same<T, JsonVariant>::value, int> = 0>
enable_if_t<!is_same<T, JsonVariant>::value, T> add() const { T add() const {
return add<JsonVariant>().template to<T>(); return add<JsonVariant>().template to<T>();
} }
// Appends a new (null) element to the array. // Appends a new (null) element to the array.
// Returns a reference to the new element. // Returns a reference to the new element.
// https://arduinojson.org/v7/api/jsonvariant/add/ // https://arduinojson.org/v7/api/jsonvariant/add/
template <typename T> template <typename T, enable_if_t<is_same<T, JsonVariant>::value, int> = 0>
enable_if_t<is_same<T, JsonVariant>::value, T> add() const; T add() const;
// Appends a value to the array. // Appends a value to the array.
// https://arduinojson.org/v7/api/jsonvariant/add/ // https://arduinojson.org/v7/api/jsonvariant/add/
@ -126,7 +126,7 @@ class VariantRefBase : public VariantTag {
// Appends a value to the array. // Appends a value to the array.
// https://arduinojson.org/v7/api/jsonvariant/add/ // https://arduinojson.org/v7/api/jsonvariant/add/
template <typename T, typename = enable_if_t<!is_const<T>::value>> template <typename T, enable_if_t<!is_const<T>::value, int> = 0>
bool add(T* value) const { bool add(T* value) const {
return detail::VariantData::addValue(getOrCreateData(), value, return detail::VariantData::addValue(getOrCreateData(), value,
getResourceManager()); getResourceManager());
@ -140,24 +140,24 @@ class VariantRefBase : public VariantTag {
// Removes a member of the object. // Removes a member of the object.
// https://arduinojson.org/v7/api/jsonvariant/remove/ // https://arduinojson.org/v7/api/jsonvariant/remove/
template <typename TChar> template <typename TChar, enable_if_t<IsString<TChar*>::value, int> = 0>
enable_if_t<IsString<TChar*>::value> remove(TChar* key) const { void remove(TChar* key) const {
VariantData::removeMember(getData(), adaptString(key), VariantData::removeMember(getData(), adaptString(key),
getResourceManager()); getResourceManager());
} }
// Removes a member of the object. // Removes a member of the object.
// https://arduinojson.org/v7/api/jsonvariant/remove/ // https://arduinojson.org/v7/api/jsonvariant/remove/
template <typename TString> template <typename TString, enable_if_t<IsString<TString>::value, int> = 0>
enable_if_t<IsString<TString>::value> remove(const TString& key) const { void remove(const TString& key) const {
VariantData::removeMember(getData(), adaptString(key), VariantData::removeMember(getData(), adaptString(key),
getResourceManager()); getResourceManager());
} }
// Removes a member of the object or an element of the array. // Removes a member of the object or an element of the array.
// https://arduinojson.org/v7/api/jsonvariant/remove/ // https://arduinojson.org/v7/api/jsonvariant/remove/
template <typename TVariant> template <typename TVariant, enable_if_t<IsVariant<TVariant>::value, int> = 0>
enable_if_t<IsVariant<TVariant>::value> remove(const TVariant& key) const { void remove(const TVariant& key) const {
if (key.template is<size_t>()) if (key.template is<size_t>())
remove(key.template as<size_t>()); remove(key.template as<size_t>());
else else
@ -170,43 +170,40 @@ class VariantRefBase : public VariantTag {
// DEPRECATED: use obj[key].is<T>() instead // DEPRECATED: use obj[key].is<T>() instead
// https://arduinojson.org/v7/api/jsonvariant/containskey/ // https://arduinojson.org/v7/api/jsonvariant/containskey/
template <typename TString> template <typename TString, enable_if_t<IsString<TString>::value, int> = 0>
ARDUINOJSON_DEPRECATED("use obj[key].is<T>() instead") ARDUINOJSON_DEPRECATED("use obj[key].is<T>() instead")
enable_if_t<IsString<TString>::value, bool> containsKey( bool containsKey(const TString& key) const;
const TString& key) const;
// DEPRECATED: use obj["key"].is<T>() instead // DEPRECATED: use obj["key"].is<T>() instead
// https://arduinojson.org/v7/api/jsonvariant/containskey/ // https://arduinojson.org/v7/api/jsonvariant/containskey/
template <typename TChar> template <typename TChar, enable_if_t<IsString<TChar*>::value, int> = 0>
ARDUINOJSON_DEPRECATED("use obj[\"key\"].is<T>() instead") ARDUINOJSON_DEPRECATED("use obj[\"key\"].is<T>() instead")
enable_if_t<IsString<TChar*>::value, bool> containsKey(TChar* key) const; bool containsKey(TChar* key) const;
// DEPRECATED: use obj[key].is<T>() instead // DEPRECATED: use obj[key].is<T>() instead
// https://arduinojson.org/v7/api/jsonvariant/containskey/ // https://arduinojson.org/v7/api/jsonvariant/containskey/
template <typename TVariant> template <typename TVariant, enable_if_t<IsVariant<TVariant>::value, int> = 0>
ARDUINOJSON_DEPRECATED("use obj[key].is<T>() instead") ARDUINOJSON_DEPRECATED("use obj[key].is<T>() instead")
enable_if_t<IsVariant<TVariant>::value, bool> containsKey( bool containsKey(const TVariant& key) const;
const TVariant& key) const;
// Gets or sets an object member. // Gets or sets an object member.
// https://arduinojson.org/v7/api/jsonvariant/subscript/ // https://arduinojson.org/v7/api/jsonvariant/subscript/
template <typename TString> template <typename TString, enable_if_t<IsString<TString>::value, int> = 0>
FORCE_INLINE enable_if_t<IsString<TString>::value, FORCE_INLINE MemberProxy<TDerived, AdaptedString<TString>> operator[](
MemberProxy<TDerived, AdaptedString<TString>>> const TString& key) const;
operator[](const TString& key) const;
// Gets or sets an object member. // Gets or sets an object member.
// https://arduinojson.org/v7/api/jsonvariant/subscript/ // https://arduinojson.org/v7/api/jsonvariant/subscript/
template <typename TChar> template <
FORCE_INLINE enable_if_t<IsString<TChar*>::value && !is_const<TChar>::value, typename TChar,
MemberProxy<TDerived, AdaptedString<TChar*>>> enable_if_t<IsString<TChar*>::value && !is_const<TChar>::value, int> = 0>
operator[](TChar* key) const; FORCE_INLINE MemberProxy<TDerived, AdaptedString<TChar*>> operator[](
TChar* key) const;
// Gets an object member or an array element. // Gets an object member or an array element.
// https://arduinojson.org/v7/api/jsonvariant/subscript/ // https://arduinojson.org/v7/api/jsonvariant/subscript/
template <typename TVariant> template <typename TVariant, enable_if_t<IsVariant<TVariant>::value, int> = 0>
enable_if_t<IsVariant<TVariant>::value, JsonVariantConst> operator[]( JsonVariantConst operator[](const TVariant& key) const {
const TVariant& key) const {
if (key.template is<size_t>()) if (key.template is<size_t>())
return operator[](key.template as<size_t>()); return operator[](key.template as<size_t>());
else else

View File

@ -67,34 +67,30 @@ inline void convertToJson(const VariantRefBase<TDerived>& src,
} }
template <typename TDerived> template <typename TDerived>
template <typename T> template <typename T, enable_if_t<is_same<T, JsonVariant>::value, int>>
inline enable_if_t<is_same<T, JsonVariant>::value, T> inline T VariantRefBase<TDerived>::add() const {
VariantRefBase<TDerived>::add() const {
return JsonVariant( return JsonVariant(
detail::VariantData::addElement(getOrCreateData(), getResourceManager()), detail::VariantData::addElement(getOrCreateData(), getResourceManager()),
getResourceManager()); getResourceManager());
} }
template <typename TDerived> template <typename TDerived>
template <typename TString> template <typename TString, enable_if_t<IsString<TString>::value, int>>
inline enable_if_t<IsString<TString>::value, bool> inline bool VariantRefBase<TDerived>::containsKey(const TString& key) const {
VariantRefBase<TDerived>::containsKey(const TString& key) const {
return VariantData::getMember(getData(), adaptString(key), return VariantData::getMember(getData(), adaptString(key),
getResourceManager()) != 0; getResourceManager()) != 0;
} }
template <typename TDerived> template <typename TDerived>
template <typename TChar> template <typename TChar, enable_if_t<IsString<TChar*>::value, int>>
inline enable_if_t<IsString<TChar*>::value, bool> inline bool VariantRefBase<TDerived>::containsKey(TChar* key) const {
VariantRefBase<TDerived>::containsKey(TChar* key) const {
return VariantData::getMember(getData(), adaptString(key), return VariantData::getMember(getData(), adaptString(key),
getResourceManager()) != 0; getResourceManager()) != 0;
} }
template <typename TDerived> template <typename TDerived>
template <typename TVariant> template <typename TVariant, enable_if_t<IsVariant<TVariant>::value, int>>
inline enable_if_t<IsVariant<TVariant>::value, bool> inline bool VariantRefBase<TDerived>::containsKey(const TVariant& key) const {
VariantRefBase<TDerived>::containsKey(const TVariant& key) const {
return containsKey(key.template as<const char*>()); return containsKey(key.template as<const char*>());
} }
@ -123,17 +119,16 @@ inline ElementProxy<TDerived> VariantRefBase<TDerived>::operator[](
} }
template <typename TDerived> template <typename TDerived>
template <typename TChar> template <typename TChar,
inline enable_if_t<IsString<TChar*>::value && !is_const<TChar>::value, enable_if_t<IsString<TChar*>::value && !is_const<TChar>::value, int>>
MemberProxy<TDerived, AdaptedString<TChar*>>> inline MemberProxy<TDerived, AdaptedString<TChar*>>
VariantRefBase<TDerived>::operator[](TChar* key) const { VariantRefBase<TDerived>::operator[](TChar* key) const {
return {derived(), adaptString(key)}; return {derived(), adaptString(key)};
} }
template <typename TDerived> template <typename TDerived>
template <typename TString> template <typename TString, enable_if_t<IsString<TString>::value, int>>
inline enable_if_t<IsString<TString>::value, inline MemberProxy<TDerived, AdaptedString<TString>>
MemberProxy<TDerived, AdaptedString<TString>>>
VariantRefBase<TDerived>::operator[](const TString& key) const { VariantRefBase<TDerived>::operator[](const TString& key) const {
return {derived(), adaptString(key)}; return {derived(), adaptString(key)};
} }
@ -153,27 +148,24 @@ inline bool VariantRefBase<TDerived>::doSet(const T& value, true_type) const {
} }
template <typename TDerived> template <typename TDerived>
template <typename T> template <typename T, enable_if_t<is_same<T, JsonArray>::value, int>>
inline enable_if_t<is_same<T, JsonArray>::value, JsonArray> inline JsonArray VariantRefBase<TDerived>::to() const {
VariantRefBase<TDerived>::to() const {
return JsonArray( return JsonArray(
VariantData::toArray(getOrCreateData(), getResourceManager()), VariantData::toArray(getOrCreateData(), getResourceManager()),
getResourceManager()); getResourceManager());
} }
template <typename TDerived> template <typename TDerived>
template <typename T> template <typename T, enable_if_t<is_same<T, JsonObject>::value, int>>
enable_if_t<is_same<T, JsonObject>::value, JsonObject> JsonObject VariantRefBase<TDerived>::to() const {
VariantRefBase<TDerived>::to() const {
return JsonObject( return JsonObject(
VariantData::toObject(getOrCreateData(), getResourceManager()), VariantData::toObject(getOrCreateData(), getResourceManager()),
getResourceManager()); getResourceManager());
} }
template <typename TDerived> template <typename TDerived>
template <typename T> template <typename T, enable_if_t<is_same<T, JsonVariant>::value, int>>
enable_if_t<is_same<T, JsonVariant>::value, JsonVariant> JsonVariant VariantRefBase<TDerived>::to() const {
VariantRefBase<TDerived>::to() const {
auto data = getOrCreateData(); auto data = getOrCreateData();
auto resources = getResourceManager(); auto resources = getResourceManager();
detail::VariantData::clear(data, resources); detail::VariantData::clear(data, resources);