假设我有一个像这样定义的类“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等不能解析为常量表达式?这看起来很奇怪......或者我做错了什么?
答案 0 :(得分:6)
switch语句中的标签必须是“整数常量表达式”(§6.4.2/ 2)。积分常数表达式“定义为(§5.19/ 1):
一个整数常量表达式只能包含文字(2.13),枚举数,常量变量或用常量表达式(8.5)初始化的整数或枚举类型的静态数据成员,整数或枚举类型的非类型模板参数,以及sizeof表达式。浮动文字(2.13.3)只有在转换为整数或枚举类型时才会出现。只能使用转换为整数或枚举类型的转换。特别是,除了sizeof表达式外,不应使用函数,类对象,指针或引用,也不得使用赋值,递增,递减,函数调用或逗号运算符。
因此,您不能进行函数调用(包括转换函数),并且数据成员必须是静态的(您的数据成员不是)。
答案 1 :(得分:1)
开关标签必须是编译时常量。在运行时创建CODE_XXX
对象之后,您要比较的值才可用。
答案 2 :(得分:0)
switch case语句的case标签应该是编译时常量并且必须是整数。 CODE_ONE,CODE_TWO等不是编译时积分常量。
参见6.4.2 / 2
答案 3 :(得分:0)
CODE_ONE,...等被定义为const的事实并不意味着它们实际上是常量表达式。所有const都是'try'并强制执行这些类实例不会被const定义的规则更改。最后,类(或该结构的结构)实例永远不会被视为完全常量表达式,因为它是一个动态对象。
switch语句需要的是一个“编译时常量表达式”,它对于C ++ 98的所有意图和目的都是一个int文字或枚举值(最后也是int literal)。
C++0x' constexpr会让你做更复杂的事情,比如使用常量函数,但不能用你要求的东西。