Raw_Potato
Raw_Potato

Reputation: 11

conflicting declaration of constexpr static struct class member

I'm trying to declare a constexpr static struct array as a class member,but When i compile the following code:

#include<iostream>
#include<assert.h>

using namespace std;

typedef enum token_t {INTEGER,SIGN,EOE} token_t;

class Token{
        token_t type;
        int value;

        constexpr static struct token_d {
            token_t id;
            const char* name;

        } token_dump[] = {
            {INTEGER,"INTEGER"},
            {SIGN,"SIGN"},
            {EOE,"EOE"}
        };

    public:
        const char* get_token_type ();
        Token(token_t,int);
};

constexpr struct token_d Token::token_dump[];

const char* Token::get_token_type ()    {
    return token_dump[type].name;
};


Token::Token (token_t TokenType,int TokenValue) {
    type = TokenType;
    value = TokenValue;
};


int main()
{
    Token token1(INTEGER,2);
    cout<<token1.get_token_type();
    return 0;
}

I get the following error messages:

calc1.cpp:29:44: error: conflicting declaration ‘constexpr const token_d Token::token_dump []’
 constexpr struct token_d Token::token_dump[];
                                            ^
calc1.cpp:18:5: note: previous declaration as ‘constexpr const Token::token_d Token::token_dump [3]’
   } token_dump[] = {
     ^~~~~~~~~~
calc1.cpp:29:44: error: declaration of ‘constexpr const Token::token_d Token::token_dump [3]’ outside of class is not definition [-fpermissive]
 constexpr struct token_d Token::token_dump[];

How can i define token_dump[]? I can't figure it out.

calc1.cpp:29:44: error: conflicting declaration ‘constexpr const token_d Token::token_dump []’ constexpr struct token_d Token::token_dump[]; ^ calc1.cpp:18:5: note: previous declaration as ‘constexpr const Token::token_d Token::token_dump [3]’ } token_dump[] = { ^~~~~~~~~~ calc1.cpp:29:44: error: declaration of ‘constexpr const Token::token_d Token::token_dump [3]’ outside of class is not definition [-fpermissive] constexpr struct token_d Token::token_dump[];

Upvotes: 1

Views: 1369

Answers (2)

M.M
M.M

Reputation: 141618

The relevant line of code should be:

constexpr Token::token_d Token::token_dump[];

When you defined struct token_d inside class Token, it means you are defining the struct Token::token_d, in other words it is scoped to that class. There is no name token_d at global scope.

When you write struct token_d at global scope, it declares token_d at global scope as a struct type, which is currently an incomplete type, and unrelated to Token::token_d. Hence the type mismatch.

I would recommend not writing struct T to refer to a pre-existing T for exactly this reason (amongst others): if you are trying to refer to a pre-existing T but you made a mistake, it will declare a new incomplete type instead of giving an error in some situations.


Regarding the discussion about the need for an out-of-class definition for static class member variables: C++17 is adding the concept of inline variables, which is quite similar to inline functions in that you can define an inline variable in the header, and the compiler sorts it all out. constexpr on a variable definition will imply inline. But prior to C++17 you still need to manually pick a translation unit to put an out-of-class definition in.

Upvotes: 1

budjmt
budjmt

Reputation: 135

I just verified it in wandbox, (I wasn't 100% sure this would compile since you're using some C-style conventions) but all that's blocking this code is your second declaration of token_dump. static constexpr variables, like other constexpr variables, are defined inline. They ignore the normal class static requirements of being defined externally.

I couldn't get this code to compile in any of the online compilers below C++17. This version moves the declaration of token_dump into the get_token_type function. I don't know exactly why, but they can't locate the variable inside that function if it's in the class.

Upvotes: 0

Related Questions