0

I have some code which has some code that looks like this one here (I simplified it, of course)

#define ERROR 0

namespace lib{
    class Logger{
         public:
             typedef enum {ERROR = 1} LogLevel;
    };
}

When compiling in visual studio I get the error: syntax error: 'constant'. It is clear that the problem is that I am re-using the word ERROR for the define and the typedef enum.

Does anyone know the logic of the define influencing some variable name that is is fact included inside a namespace and a class. I mean, how can ERROR be confused with lib::Logger::ERROR since my guess is that they have completely different scopes.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
  • 6
    It's a macro. That means that every place where the compiler sees `ERROR` it replaces it with `0`. And, no, it doesn't "compile with g++". Something else might compile, but this code won't. – Pete Becker Dec 13 '17 at 15:30
  • 2
    The main reason is that you've adopted a Java/Python convention, namely uppercase for constants, in C++ where it Does Not Make Sense. – Cheers and hth. - Alf Dec 13 '17 at 15:30
  • 2
    **−1** For posting code that is **not the real code**. – Cheers and hth. - Alf Dec 13 '17 at 15:32
  • You are right @Pete Becker, it does not compile in g++, I just realised the define actually comes from a windows default include wingdi.h that does not exists when compiling with g++. This the preprocessor might even replace variable names, I guess. Thanks. – Jordi Adell Dec 13 '17 at 15:32
  • `namesspace` O RLY? Post the actual code you're using, which is presumably not that, or you'd be getting a different problem. – underscore_d Dec 13 '17 at 15:37
  • Hi! Just ran into exactly this problem where a colleague used ALL CAPS for enum values... Some never learn, and some have never learnt. – U. W. Dec 08 '20 at 14:45

1 Answers1

7

Preprocessor #define substitution is one of the first things to happen when you compile your code. These substitutions are made textually and ignore c++ syntax. Your code is equivalent to :

namespace lib{
    class Logger{
         public:
             typedef enum {0 = 1} LogLevel;
    };
}

It's obvious that, after the substitution of ERROR with 0 your enum definition is ill-formed.

Using preprocessor marcos is generally seen as a bad idea if any other mechanism can do the same job instead. This question illustrates one of the many risks associated with using them. See the question Why are preprocessor macros evil and what are the alternatives?.

François Andrieux
  • 28,148
  • 6
  • 56
  • 87
  • @FrançoisAndrieux Probably worth throwing in that macros are considered evil in general usage with a number of levels of hell reserved for their misuse; but have an upvote for being able to understand that namesspace was a typo. – UKMonkey Dec 13 '17 at 15:45