bblanchon/ArduinoJson

Replacing deprecated 'containsKey' with is<T> in a template fails to compile

MartinMueller2003 opened this issue · 3 comments

Description
Updating a set of templates that have been working for a long time, fails.
Same code placed directly in a 'cpp' file works properly.

Troubleshooter's report

  1. The program uses ArduinoJson 7
  2. The issue happens at compile time
  3. The error is not in the list

Environment

Reproduction code

template <typename T, typename J, typename K>
bool setFromJSON (T& OutValue, J& Json, K Key)
{
    bool HasBeenModified = false;

    if (Json[Key].is<T>())
    {
        T temp = Json[Key];
        if (temp != OutValue)
        {
            OutValue = temp;
            HasBeenModified = true;
        }
    }
    else
    {
        DEBUG_V(String("Could not find field '") + Key + "' in the json record");
    }

    return HasBeenModified;
}; // setFromJSON

Remarks
Usage:
ConfigChanged |= setFromJSON (config.id, JsonDeviceConfig, CN_id);
String, JsonObject, const char *

Compiler output:
ESPixelStick/src/input/../ESPixelStick.h: In function 'bool setFromJSON(T&, J&, K)':
ESPixelStick/src/input/../ESPixelStick.h:113:23: error: expected primary-expression before '>' token
if (Json[Key].is())
^
ESPixelStick/src/input/../ESPixelStick.h:113:25: error: expected primary-expression before ')' token
if (Json[Key].is())

Hi @MartinMueller2003,

Since J is a template parameter, the compiler cannot know that J is supposed to be a class that supports a template member function is<T>(), so it incorrectly assumes that you wanted to use the < operator on a member variable, like so:

Json[Key].is < T > ()  // error: expected primary-expression before '>' token

That's why you get this curious error: the compiler expected T to be a primary expression, not a type.

To fix this, you must convince the compiler that the < sign is not a comparison operator but the beginning of a template argument list. This is done by replacing . with .template like so:

if (Json[Key].template is<T>())

Note that you wouldn't have had this error if you had used JsonVariant or JsonObject for the type of the Json argument instead of a template parameter.

Best regards,
Benoit

Thank You. That works

I did not specify JsonVariant or JsonObject because both of them are passed as the Json data be different callers. Just using the power of templates :)

You're welcome, @MartinMueller2003.
Thank you for using ArduinoJson!
Don't forget to cast a star to support the project 😉