NmdMystery
NmdMystery

Reputation: 2878

Macro not declared in this scope

I'm using a preprocessor #define macro to count the number of functions in a header file:

#define __INDEX -1

//First group of functions
void func1(void);
#define __FUNC1_INDEX __INDEX + 1
void func2(void);
#define __FUNC2_INDEX __FUNC1_INDEX + 1
#undef __INDEX
#define __INDEX __FUNC2_INDEX

//Second group of functions
void func3(void);
#define __FUNC3_INDEX __INDEX + 1
void func4(void);
#define __FUNC4_INDEX __FUNC3_INDEX + 1
#undef __INDEX
#define __INDEX __FUNC4_INDEX

//Third group of functions
void func5(void);
#define __FUNC5_INDEX __INDEX + 1
void func6(void);
#define __FUNC6_INDEX __FUNC5_INDEX + 1
#undef __INDEX
#define __INDEX __FUNC6_INDEX

#define __NUM_FUNCTIONS __INDEX + 1

The preprocessor gets through the first two sets of functions just fine, but when it reaches the line:

#define __FUNC5_INDEX __INDEX + 1

I get a "not defined in this scope" error for __INDEX. What makes this really confusing is the fact that the same exact thing is done [successfully] in the second group of functions; __FUNC3_INDEX takes on the value of __INDEX + 1. There's no typos anywhere, as far as I can tell... what's the problem?

I'm using g++ 4.8.

Upvotes: 1

Views: 5919

Answers (1)

rici
rici

Reputation: 241861

You can't count with preprocessor macros. They are just string expansions.

After the preprocessor finishes with this:

#define __FUNC5_INDEX __INDEX + 1
#define __FUNC6_INDEX __FUNC5_INDEX + 1
#undef __INDEX
#define __INDEX __FUNC6_INDEX

The following definitions are in effect:

__FUNC5_INDEX → __INDEX + 1
__FUNC6_INDEX → __FUNC5_INDEX + 1
__INDEX → __FUNC6_INDEX

No computation has been done. What's more, no replacement is performed inside a #define directive.

Now, when you attempt to expand __INDEX (possibly as part of an expansion of __NUM_FUNCTIONS, the following will happen:

__INDEX → __FUNC6_INDEX
        → __FUNC5_INDEX + 1
        → __INDEX + 1 + 1

At this point, the macro expansion stops because you cannot expand a macro inside of its own expansion. The token is just left as-is.

Consequently, you'll end up using the symbol __INDEX inside the program, as a variable. But since the variable __INDEX has never been defined, you get an error.

By the way, don't use symbols starting with two underscores, or with one underscore and a capital letter. Those are reserved for the standard library.

Upvotes: 2

Related Questions