3

I was surprised to learn that g++ (4.9) was compiling this (while gcc would not):

#include <stdio.h>

enum
{
    ONE   = 1,
    TWO   = 2,
    THREE = 3
};

int main(int argc, char* argv[])
{
    int sw = 2;

    switch (sw)
    {
    case::ONE:
    {
        printf("1\n");
        break;
    }

    case::TWO:
    {
        printf("2\n");
        break;
    }

    case::THREE:
    {
        printf("3\n");
        break;
    }

    default:
    {
        printf("default\n");
    }
    }
}

How is the g++ preprocessor able to separate the "case" from the "::ONE:"?

P.P
  • 117,907
  • 20
  • 175
  • 238
John
  • 2,326
  • 1
  • 19
  • 25

4 Answers4

4

How is the g++ preprocessor able to separate the "case" from the "::ONE:"?

It's not the preprocessor, but simply the compiler, that interprets :: to refer to the global namespace.

The case labels will be parsed as

case :: THREE :

and that's perfectly OK, as your enum values appear in the global namespace (::).

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
3

It is not the preprocessor. The C compiler (its tokenizer) sees that as:

case :: ONE

which is ok in c++. The :: operator means the root namespace. C has no such thing.

Cecilio Pardo
  • 1,717
  • 10
  • 13
0

You have a simple enum, not a scoped enum (see: enum class). Plain enums are in the root scope, hence you can write ::ONE.

With scoped enums, you can do the following:

enum class Scoped { FIRST, LAST = 9};
//...
case Scoped::FIRST : //...

The tokenizer in g++ (as this is a C++ feature) can resolve even if you don't leave whitespaces between the case keyword and the enumerator.

Koshinae
  • 2,240
  • 2
  • 30
  • 40
0

During the lexical analysis phase of the compilation process, the stream of characters in the program file is converted to tokens. One of the popular algorithms used here is maximal munch in which the longest matching legal token is considered as the intended token. In this example, it breaks the case::ONE: into case, ::, ONE and :.

There are also some disadvantages: x = y/*z is an error since /* is the longest matching legal token, while the user probably wanted to say x = y / *z. You can find many such curious examples, couple of them are here and here.

Community
  • 1
  • 1
Erobrere
  • 388
  • 1
  • 12