BUG? " error: 'x' redeclared as different kind of symbol

The code is a simple function template at global scope in the .ino file, right before setup():

    template <typename T>
    static constexpr char item_code (T val)
    {
        return ( 'x' );
    };

There is no other code than the empty setup() {} and loop() {} definitions.

I get the following errors:

error: 'constexpr const char item_code' redeclared as different kind of symbol
     static constexpr char item_code (T val)
                                      ^
<Sketch folder>/redeclare.ino:22:23: note: previous declaration 'template<class T> constexpr char item_code(T)'
     static constexpr char item_code (T val)
                       ^
redeclare:22:38: error: 'T' was not declared in this scope
     static constexpr char item_code (T val)

I cannot see anything wrong, and the error messages are fishy. This is confirmed by the fact that if I make the template a class member, there is no error. Further, if I move the template to a .h file and #include that in the .ino, there is no error, even though the template is again at global scope.

So I suspect this is a quirk/bug of Arduino, - but I could be missing something subtle... It's not going to be a serious issue for me, as I only ever put code in a .ino for small tests, but it did cause me a considerable amount of head-scratching.

Any comments?

Hi
I don't understand this line.

Try it like this:

  template <typename T>
    // static constexpr
     char item_code (T val)
     {
         return('x');
     }; 

Here is a minimal version of the sketch:

template <typename T>
static constexpr char item_code (T val)
{
    return ( 'x' );
};
void setup() {}
void loop() {}

Here is what it looks like after sketch preprocessing:

#include <Arduino.h>
#line 1 "C:\\Users\\asdf\\AppData\\Local\\Temp\\.arduinoIDE-unsaved20211125-14436-1wjg3vl.8p9s\\sketch_dec25a\\sketch_dec25a.ino"
template <typename T>
#line 2 "C:\\Users\\asdf\\AppData\\Local\\Temp\\.arduinoIDE-unsaved20211125-14436-1wjg3vl.8p9s\\sketch_dec25a\\sketch_dec25a.ino"
static constexpr char item_code(T val);
#line 6 "C:\\Users\\asdf\\AppData\\Local\\Temp\\.arduinoIDE-unsaved20211125-14436-1wjg3vl.8p9s\\sketch_dec25a\\sketch_dec25a.ino"
void setup();
#line 7 "C:\\Users\\asdf\\AppData\\Local\\Temp\\.arduinoIDE-unsaved20211125-14436-1wjg3vl.8p9s\\sketch_dec25a\\sketch_dec25a.ino"
void loop();
#line 2 "C:\\Users\\asdf\\AppData\\Local\\Temp\\.arduinoIDE-unsaved20211125-14436-1wjg3vl.8p9s\\sketch_dec25a\\sketch_dec25a.ino"
static constexpr char item_code (T val)
{
    return ( 'x' );
};
void setup() {}
void loop() {}

Hi
I'm not a software expert
I try it this way and compiled: I have remove "static ".

template <typename T>
constexpr char item_code (T val)
{
    return ( 'x' );
};
void setup() {}
void loop() {}

Try putting the template definition in a .h file and #include it

The line is to define a constexpr function that will be usable at compilation time, and the static means it will not be visible in other compilation units (internal linkage). Think I got that right, and I think it's legal. It's what I thought I wanted, though in actual use, it won't be in the .ino, it will be in a header file.

Yes, it compiles without the 'static constexpr' and also just without the 'static'. It does also, as I mentioned, compile with ' 'static constexpr' if moved to a header file, which is the main point to me. From the preprocessed output, it is evident that the template (or part of it) is being included twice, which perhaps explains the error message. I guess it results from the automatic generation of function prototypes as a feature of the Arduino if you put stuff in the .ino rather than in a header - and declare it static. As I said, I usually don't have anything in the .ino but function calls from setup() and loop() to the "real" functions in a .cpp, so templates will then be in a header.

Is it a bug? Maybe, if you think the code is legal, and that code ought not to do something different if it's in a .ino than when in a .cpp.

The Arduino preprocessor chokes on template declarations if the template <...> is on a separate line.

Try this:

template <typename T> static constexpr char item_code (T val) {
    return 'x' ; // Also note that `return` is not a function
};

No joy.
This sketch:

template <typename T> static constexpr char item_code (T val) {
    return 'x' ; // Also note that `return` is not a function
};
void setup() {}
void loop() {}

Preprocessed:

#include <Arduino.h>
#line 1 "C:\\Users\\asdf\\AppData\\Local\\Temp\\.arduinoIDE-unsaved20211125-16368-sqcg77.hgt1k\\sketch_dec25b\\sketch_dec25b.ino"
#line 1 "C:\\Users\\asdf\\AppData\\Local\\Temp\\.arduinoIDE-unsaved20211125-16368-sqcg77.hgt1k\\sketch_dec25b\\sketch_dec25b.ino"
static constexpr char item_code(T val);
#line 4 "C:\\Users\\asdf\\AppData\\Local\\Temp\\.arduinoIDE-unsaved20211125-16368-sqcg77.hgt1k\\sketch_dec25b\\sketch_dec25b.ino"
void setup();
#line 5 "C:\\Users\\asdf\\AppData\\Local\\Temp\\.arduinoIDE-unsaved20211125-16368-sqcg77.hgt1k\\sketch_dec25b\\sketch_dec25b.ino"
void loop();
#line 1 "C:\\Users\\asdf\\AppData\\Local\\Temp\\.arduinoIDE-unsaved20211125-16368-sqcg77.hgt1k\\sketch_dec25b\\sketch_dec25b.ino"
template <typename T> static constexpr char item_code (T val) {
    return 'x' ; // Also note that `return` is not a function
};
void setup() {}
void loop() {}

That looks like a regression bug. I swear it used to work in older releases.

Just tested it: I get the same results as you did in recent versions of the IDE, but in 1.8.1, I do get the right result:

# 1 "C:\\Users\\user\\AppData\\Local\\Temp\\arduino_modified_sketch_895048\\Blink.ino"
# 1 "C:\\Users\\user\\AppData\\Local\\Temp\\arduino_modified_sketch_895048\\Blink.ino"
template <typename T> static constexpr char item_code (T val) {
    return 'x' ; // Also note that `return` is not a function
};
void setup() {}
void loop() {}

Edit: they even had a test for this, but they moved it to the legacy folder and now it's broken :frowning:

Edit 2: This is the preprocessed code generated by Arduino 1.8.19. For some reason, it loses the template <...> and the constexpr:

#include <Arduino.h>
#line 1 "C:\\Users\\user\\Documents\\Arduino\\sketch_dec26a\\sketch_dec26a.ino"
#line 1 "C:\\Users\\user\\Documents\\Arduino\\sketch_dec26a\\sketch_dec26a.ino"
static char func(T val);
#line 4 "C:\\Users\\user\\Documents\\Arduino\\sketch_dec26a\\sketch_dec26a.ino"
void setup();
#line 5 "C:\\Users\\user\\Documents\\Arduino\\sketch_dec26a\\sketch_dec26a.ino"
void loop();
#line 1 "C:\\Users\\user\\Documents\\Arduino\\sketch_dec26a\\sketch_dec26a.ino"
template <typename T> constexpr static char func(T val) {
    return 'x' ; // Also note that `return` is not a function
}
void setup() {}
void loop() {}

As already surmised, you're a victim of the Arduino IDE's "helpful" auto-prototype generation. Your original code compiles fine in Sloeber / Eclipse. Just as well, the Arduino IDE is not suitable for any serious code development anyway.

Yes, I was checking my inferences and noticed the template line was getting lost, so I did try putting it on one line, but no joy.

I realize the "return 'x'" is not a function, but it doesn't have to be. It was the simplest thing I could try for demo purposes. Though useless, it's certainly legal. The actual project uses a bunch of TMP stuff to look at object types and deliver a code representing the type of the object.

I am using 1.8.16, though usually I work with Visual Micro in Visual Studio. I mostly turn off or bypass the Arduino "improvements". I would agree the Arduino IDE is not a serious environment (after using VS/VM it is painful), though the amount of code freely available for Arduino is staggering. For an embedded project, it's hard to beat as a starting point.