C++ 编译器无法正确识别枚举

发布于 2024-07-15 04:58:17 字数 491 浏览 6 评论 0原文

谁能解释为什么以下代码无法编译(在 g++ (GCC) 3.2.3 20030502 (Red Hat Linux 3.2.3-49) 上)?

struct X {
public:
   enum State { A, B, C };

   X(State s) {}
};

int main()
{
   X(X::A);
}

我收到的消息是:

jjj.cpp: In function 'int main()':
jjj.cpp:10: 'XX::A' 不是 'struct X' 的静态成员
jjj.cpp:10: 没有匹配的函数可用于调用“X::X()”
jjj.cpp:1:候选者是:X::X(const X&)
jjj.cpp:5: X::X(X::State)`

这是错误的代码还是编译器错误?

尼尔+康拉德解决了这个问题。 请参阅下面对尼尔的回答的评论。

Can anyone explain why the following code does not compile (on g++ (GCC) 3.2.3 20030502 (Red Hat Linux 3.2.3-49))?

struct X {
public:
   enum State { A, B, C };

   X(State s) {}
};

int main()
{
   X(X::A);
}

The message I get is:

jjj.cpp: In function 'int main()':
jjj.cpp:10: 'X X::A' is not a static member of 'struct X'
jjj.cpp:10: no matching function for call to 'X::X()'
jjj.cpp:1: candidates are: X::X(const X&)
jjj.cpp:5: X::X(X::State)`

Is this bad code or a compiler bug?

Problem solved by Neil+Konrad. See the comments to Neil's answer below.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

冷…雨湿花 2024-07-22 04:58:18

您忘记了定义中的变量名称:

int main()
{
   X my_x(X::A);
}

您的代码使编译器感到困惑,因为从语法上讲,它无法将其与函数声明区分开来(返回 X 并传递 X::A 作为参数)。 当有疑问时,C++ 编译器总是消除歧义并支持声明。

解决方案是在 X 周围引入多余的括号,因为编译器禁止在类型周围使用括号(而不是构造函数调用等):

(X(X::A));

You've forgot the variable name in your definition:

int main()
{
   X my_x(X::A);
}

Your code confuses the compiler because syntactically it can't distinguish this from a function declaration (returning X and passing X::A as an argument). When in doubt, the C++ compiler always disambiguates in favour of a declaration.

The solution is to introduce redundant parentheses around the X since the compiler forbids parentheses around types (as opposed to constructo calls etc.):

(X(X::A));
街道布景 2024-07-22 04:58:18
X(X::A);

被视为函数声明。 如果您确实想要此代码,请使用:

(X)(X::A);
X(X::A);

is being seen a s a function declaration. If you really want this code, use:

(X)(X::A);
亽野灬性zι浪 2024-07-22 04:58:18

只是为了让大家清楚地了解发生了什么。 看这个例子

int main() {
    float a = 0;
    {
        int(a); // no-op?
        a = 1;
    }
    cout << a;
}

它会输出什么? 嗯,它会输出0。 上面的 int(a) 可以用两种不同的方式解析:

  • 转换为 int 并丢弃结果
  • 声明一个名为 a 的变量。 但请忽略标识符周围的括号。

当出现在语句中使用函数式强制转换并且看起来也像声明的情况时,编译器总是将其视为声明。 当它在语法上不能是声明时(编译器将查看整行来确定),它将被视为表达式。 因此,我们将分配给上面的内部 a,而将外部 a 保留为零。

现在,你的情况正是如此。 您试图(不小心)在名为 X 的类中声明一个名为 A 的标识符:

X (X::A); // parsed as X X::A;

然后编译器会继续抱怨未声明的默认构造函数,因为静态、正如它所假设的那样,是默认构造的。 但即使你有 X 的默认构造函数,它当然仍然是错误的,因为 A 都不是 X 的静态成员,也不能在块作用域中定义/声明 X 的静态成员。

您可以通过执行几项操作来使其不像看起来像一个声明。 首先,您可以将整个表达式加括号,这使其看起来不再像声明。 或者只是将要转换的类型括起来。 其他答案中已经提到了这两种消歧义:

(X(X::A)); (X)(X::A)

当您尝试实际声明一个对象时,存在类似但明显的歧义。 看这个例子:

int main() {
    float a = 0;
    int b(int(a)); // object or function?
}

因为 int(a) 既可以是名为 a 的参数的声明,也可以是 float 变量到 int 的显式转换(强制转换),编译器再次决定这是一个声明。 因此,我们碰巧声明了一个名为 b 的函数,它接受一个整数参数并返回一个整数。 根据上述消歧,有几种可能的方式来消除歧义:

int b((int(a))); int b((int)a);

Just to make it crystal clear what happens. Look at this example

int main() {
    float a = 0;
    {
        int(a); // no-op?
        a = 1;
    }
    cout << a;
}

What will it output? Well, it will output 0. The int(a) of above can be parsed in two different ways:

  • Cast to int and discard the result
  • Declare a variable called a. But ignore the parentheses around the identifier.

The compiler, when such a situation appears where a function-style cast is used in a statement and it looks like a declaration too, will always take it as a declaration. When it can't syntactically be a declaration (the compiler will look at the whole line to determine that), it will be taken to be an expression. Thus we are assigning to the inner a above, leaving the outer a at zero.

Now, your case is exactly that. You are trying (accidentally) to declare an identifier called A within a class called X:

X (X::A); // parsed as X X::A;

The compiler then goes on to moan about a not declared default constructor, because the static, as it assumes it to be, is default constructed. But even if you had a default constructor for X, it of course is still wrong because neither A is a static member of X, nor a static of X can be defined/declared at block scope.

You can make it not look like a declaration by doing several things. First, you can paren the whole expression, which makes it not look like a declaration anymore. Or just paren the type that is cast to. Both of these disambiguations have been mentioned in other answers:

(X(X::A)); (X)(X::A)

There is a similar, but distinct ambiguity when you try to actually declare an object. Look at this example:

int main() {
    float a = 0;
    int b(int(a)); // object or function?
}

Because int(a) can be both the declaration of a parameter called a and the explicit conversion (cast) of the float-variable to an int, the compiler decides again that that is a declaration. Thus, we happen to declare a function called b, which takes an integer argument and returns an integer. There are several possibilities how to disambiguate that, based on the disambiguation of above:

int b((int(a))); int b((int)a);
断桥再见 2024-07-22 04:58:18

一个对象声明为Bug。

X x(X::A);

您应该在代码中将

You should declare an object as

X x(X::A);

Bug in your code.

毁我热情 2024-07-22 04:58:18

这两行代码中的任何一行都对我有用:

X obj(X::A);
X obj2 = X(X::A);

正如 Neil Butterworth 指出的那样,X(X::A) 被视为函数声明。 如果您确实想要一个匿名对象,(X)(X::A) 将构造一个 X 对象并立即删除它。

Either of these two lines work for me:

X obj(X::A);
X obj2 = X(X::A);

As Neil Butterworth points out, X(X::A) is being treated as a function declaration. If you really want an anonymous object, (X)(X::A) will construct an X object and immediately delete it.

时光匆匆的小流年 2024-07-22 04:58:18

当然,您可以这样做:

int main()
{
    // code
    {
    X temp(X::A);
    }
    // more code
}

这会更具可读性并且基本上具有相同的效果。

You could, of course, just do something like this:

int main()
{
    // code
    {
    X temp(X::A);
    }
    // more code
}

This would be more readable and basically have the same effect.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文