为什么命名枚举值 "IN" 会导致语法错误?

Why does naming an enum value "IN" cause a syntax error?

我有一个 class,其中包含长度单位的枚举。

class LengthUnit
{
public:
    enum Value
    {
        IN,
        CM,
        FT
    };
    static double convert(double value, Value from, Value to){
        if (from == to) return value;
        return value * getScale(from)/getScale(to);
    }
    constexpr LengthUnit(Value value) : value(value) {}

    bool operator==(LengthUnit lUnit) const { return value == lUnit.value; }
    bool operator!=(LengthUnit lUnit) const { return value != lUnit.value; }

private:
    static double getScale(Value value){
        switch (value){
        case IN: return 2.54; // 1 in = 2.54 cm
        case FT: return 30.48; // 1 ft = 30.48 cm
        case CM: return 1;
        default:
            throw QException();
        }
    }
    Value value;
};

第 6 行检测到错误。

error: expected identifier before ',' token
         IN,
           ^

如果我将变量名从 IN 更改为 INCHES,错误就会消失。

导致此错误的原因是什么?据我所知,IN 不是 C++ 或 Qt 的关键字,那么为什么这个名称会引起问题?

您还没有指定还包括哪些其他头文件,因此实际上不可能给出任何明确的答案。

但是,您可以采取一些措施来解决名称冲突问题:

  • 因为显然其他东西正在定义一个 IN 预处理器宏,你可以这样做: #define IN whatever after 你所有的 #includes 查看您的编译器是否会生成一条错误消息,描述它在其他地方的定义。

  • 如果这不起作用,您可以让编译器生成预处理输出(通常通过命令行选项,例如 -E)。然后您可以检查它以查看用什么替换了 IN,这可能会让您了解它的来源。

  • 在您的源(.cpp.cc)文件中,您可以在所有 #include 之后添加 #undef IN 以取消定义较早的实例,因为您可能不需要较早的定义。 (但是,不要在头文件中这样做。这样做可能会在将来引发问题。)

  • 只需重命名常量即可。正如我在评论中提到的那样,预处理器宏应该使用全大写名称(并且 用于)以避免名称冲突。不幸的是,这种做法被破坏为全大写命名 constants,但我认为为预处理器宏提供一个单独的命名空间更有用。