Comparison operators for custom types
Description
- The program uses ArduinoJson 6
- The issue happens at compile time
- The error is not in the list
See reproduction code below. Using a custom defined struct works for assignments (using Converter<>) as described in https://arduinojson.org/news/2021/05/04/version-6-18-0/
But I cannot get it to work for comparison operators (like var["value"] != value in below example).
I get this error: .pio/libdeps/esp32dev/ArduinoJson/src/ArduinoJson/Variant/VariantCompare.hpp:203:15: error: 'ArduinoJson::V6214PB2::detail::Comparer<Coordinate, void> comparer' has incomplete type Comparer<T> comparer(rhs);
Tried to add Comparer like functions but all resulted in compile errors.
Help / code example really appreciated.
Thx Ewoud
Troubleshooter's report
- The program uses ArduinoJson 6
- The issue happens at compile time
- The error is not in the list
Environment
- Microcontroller: ESP32
- Core/Framework: Expressif 3.20014.0
- IDE: VSCode 1.85 PIO v3.3.2
Reproduction code
This code:
template <typename Type>
JsonObject setValue(const char * id, Type value) {
JsonObject var = findVar(id);
if (var["value"].isNull() || var["value"] != value) {
var["value"] = value;
}
}
works for:
mdl->setValue<int>("var1", 10);
but not for:
Coordinate xyz;
xyz.x = 1;
xyz.y = 2;
xyz.z = 3;
mdl->setValue<Coordinate>("var2", xyz, 0);
This code is present:
template <>
struct Converter<Coordinate> {
static bool toJson(const Coordinate& src, JsonVariant dst) {
dst["x"] = src.x;
dst["y"] = src.y;
dst["z"] = src.z;
return true;
}
static Coordinate fromJson(JsonVariantConst src) {
return Coordinate{src["x"], src["y"], src["z"]};
}
static bool checkJson(JsonVariantConst src) {
return src["x"].is<int>() && src["y"].is<int>() && src["z"].is<int>();
}
};
Hi @MoonModules,
Comparison with custom types is not supported.
As a workaround you can do var["value"].as<Coordinate>() != value.
Best regards, Benoit
Hi Benoit, Thx for your reply.
Even better (as the function is a template):
JsonObject setValue(const char * id, Type value) {
JsonObject var = findVar(id);
if (var["value"].isNull() || var["value"].as<Type>() != value) {
var["value"] = value;
}
}
but then != was not defined for Coordinate so I changed the struct:
struct Coordinate {
uint16_t x;
uint16_t y;
uint16_t z;
bool operator!=(Coordinate par) {
return x != par.x || y != par.y || z != par.z;
}
};
And now it's perfect !
One question, is comparison with custom types not supported by design (as it should be done as shown above), or might it be a future enhancement?
Thx again,
Kind regards,
Ewoud from MoonModules
Only thing I am not sure of is if the Type is const char * then the != should be a strcmp ... could that also be overloaded (question to myself 🙂 )
In that case lot less strcmp in code which looks cleaner (but could confuse core char * people 🙂)
JsonString ... 🙂
@MoonModules, I suppose we could make this a feature, but as a wise man once wrote:
Features have a specification cost, a design cost, and a development cost. There is a testing cost and a reliability cost. The more features there are, the more likely one will develop problems or will interact badly with another. [...] Features have a documentation cost. Every feature adds pages to the manual, increasing training costs. Features that offer value to a minority of users impose a cost on all users.
It'll convert this issue to a feature request and see if more users are interested.