switch 语句中预期的常量表达式惨败
假设我有一个像这样定义的类“Code”,用户指定类型转换为 int:
class Code
{
public:
int code;
std::string description;
Code (const int c, const std::string& d) : code(c), description(d) { ; }
operator int() const { return code; }
};
以及使用代码类的第二个类“Master”:
class Master
{
public:
Code master_code;
};
以及一堆预先指定的代码,如下所示:
const Code CODE_ONE (1, "This is code one");
const Code CODE_TWO (2, "This is code two");
const Code CODE_THREE (3, "This is code three");
人们会认为(即我认为)可以这样使用它:
Master master_obj;
switch (master_obj.master_code)
{
case CODE_ONE:
// ...
break;
case CODE_TWO:
// ...
break;
case CODE_THREE:
// ...
break;
default:
// ...
}
由于自动类型转换为 int,但情况显然并非如此。 GCC 告诉我 CODE_ONE、CODE_TWO 和 CODE_THREE“不能出现在常量表达式中”。
顺便说一句,这也不起作用:
Master master_obj;
switch (master_obj.master_code)
{
case CODE_ONE.code:
// ...
break;
case CODE_TWO.code:
// ...
break;
case CODE_THREE.code:
// ...
break;
default:
// ...
}
上面返回完全相同的错误:除了“'.'之外,“'CODE_ONE'不能出现在常量表达式中”。不能出现在常量表达式中”。
但这确实有效:
Master master_obj;
switch (master_obj.master_code)
{
case 1:
// ...
break;
case 2:
// ...
break;
case 3:
// ...
break;
default:
// ...
}
所以 CODE_ONE 等不能解析为常量表达式?这看起来很奇怪……还是我做错了什么?
Say I have a class "Code" defined like this, with a user specified type conversion to int:
class Code
{
public:
int code;
std::string description;
Code (const int c, const std::string& d) : code(c), description(d) { ; }
operator int() const { return code; }
};
And a second class "Master" using the code class:
class Master
{
public:
Code master_code;
};
As well as a bunch of pre-specified codes, like this:
const Code CODE_ONE (1, "This is code one");
const Code CODE_TWO (2, "This is code two");
const Code CODE_THREE (3, "This is code three");
One would think (i.e. I would think) that one could use it like this:
Master master_obj;
switch (master_obj.master_code)
{
case CODE_ONE:
// ...
break;
case CODE_TWO:
// ...
break;
case CODE_THREE:
// ...
break;
default:
// ...
}
due to the automatic type conversion to int, but this is apparently not the case. GCC tells me that CODE_ONE, CODE_TWO and CODE_THREE "can not appear in a constant-expression".
This does not work either, by the way:
Master master_obj;
switch (master_obj.master_code)
{
case CODE_ONE.code:
// ...
break;
case CODE_TWO.code:
// ...
break;
case CODE_THREE.code:
// ...
break;
default:
// ...
}
The above returns the exact same error: "'CODE_ONE' can not appear in a constant-expression" in addition to a "'.' can not appear in a constant-expression".
But this does work:
Master master_obj;
switch (master_obj.master_code)
{
case 1:
// ...
break;
case 2:
// ...
break;
case 3:
// ...
break;
default:
// ...
}
So CODE_ONE etc. can't be resolved as constant expressions? That seems weird... Or am I doing something wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
开关标签必须是编译时常量。在运行时创建
CODE_XXX
对象之后,您要比较的值才可用。The switch labels must be compile-time constants. The values you want to compare aren't available until after the
CODE_XXX
objects have been created at runtime.switch case 语句的 case 标签应该是编译时常量并且应该是完整的。 CODE_ONE、CODE_TWO 等不是编译时积分常量。
参考6.4.2/2
Case labels of a switch case statements should be compile time constants and shall be integral. CODE_ONE, CODE_TWO etc are not compile time integral constants.
Refer 6.4.2/2
CODE_ONE、...等被定义为 const 的事实并不意味着它们实际上是常量表达式。 const 所做的只是“尝试”并强制这些类实例不会按照 const 定义的规则进行更改。最后,类(或结构)实例永远不会被视为完全常量表达式,因为它是动态对象。
switch 语句需要的是一个“编译时常量表达式”,对于 C++98 的所有意图和目的来说,它是一个 int 文字或枚举值(最后也是 int 文字)。
C++0x' constexpr 可以让你做更复杂的事情,比如使用常量函数,但不是您所要求的。
The fact that CODE_ONE, ... etc are defined as const does not mean they are actually constant expressions. All const does is 'try' and enforce that those class instances do not change by const defined rules. In the end a class(or struct for that matter) instance is never considered a fully constant expression since it is a dynamic object.
What a switch statement needs is a "compile-time constant expression" which for all intents and purposes regarding C++98 is an int literal or an enum value(also int literal in the end).
C++0x' constexpr will let you do more complex things like use constant functions, but not what you are asking for.
switch 语句中的标签必须是“整数常量表达式”(第 6.4.2/2 节)。整型常量表达式”定义为 (§5.19/1):
因此,您不能进行函数调用(包括转换函数),并且数据成员必须是静态的(您的不是静态的)。
The labels in a switch statement must be "integral constant-expressions" (§6.4.2/2). An integral constant expression" is defined as (§5.19/1):
So, you can't have a function call (including a conversion function), and a data member must be static (which yours isn't).