constexpr静态结构类成员的冲突声明

时间:2017-11-05 21:26:16

标签: c++ arrays struct static constexpr

我试图将constexpr静态结构数组声明为类成员,但是当我编译以下代码时:

#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;
}

我收到以下错误消息:

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[];

我如何定义token_dump []?我无法弄清楚。

  

calc1.cpp:29:44:错误:冲突声明'constexpr const   token_d Token :: token_dump []'constexpr struct token_d   令牌:: token_dump [];                                               ^ calc1.cpp:18:5:注意:之前的声明为'constexpr const Token :: token_d   Token :: token_dump [3]'} token_dump [] = {        ^ ~~~~~~~~~ calc1.cpp:29:44:错误:在类之外声明'constexpr const Token :: token_d Token :: token_dump [3]'   definition [-fpermissive] constexpr struct token_d   令牌:: token_dump [];

2 个答案:

答案 0 :(得分:1)

相关的代码行应为:

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

当您在struct token_d中定义class Token时,这意味着您正在定义结构Token::token_d,换句话说,它是作用于该类的范围。全局范围内没有名称token_d

当您在全局范围内编写struct token_d时,它会在全局范围内将token_d声明为结构类型,该类型当前是不完整类型,与Token::token_d无关。因此类型不匹配。

我建议不要写struct T来引用预先存在的T,原因正是如此(除其他外):如果您尝试引用预先存在的T但是你犯了一个错误,它会声明一个新的不完整类型,而不是在某些情况下给出错误。

关于需要对静态类成员变量进行类外定义的讨论:C ++ 17正在添加内联变量的概念,这与内联函数非常相似您可以在标头中定义内联变量,编译器将其全部排序。变量定义上的constexpr意味着inline。但是在C ++ 17之前,您仍然需要手动选择一个翻译单元来放置一个类外定义。

答案 1 :(得分:0)

我刚刚在wandbox验证了它,(我不是100%确定这会编译,因为你使用了一些C风格的约定)但是阻止这段代码的所有内容都是你{{1}的第二个声明}}。与其他token_dump变量一样,static constexpr变量是内联定义的。它们忽略了在外部定义的正常类静态要求。

我无法在C ++ 17以下的任何在线编译器中编译此代码。 This version将token_dump的声明移动到get_token_type函数中。我不确切知道为什么,但如果它在类中,它们无法在该函数内找到变量。