Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

At which point during preprocessing stage is __LINE__ expanded?

I have a function in a header file:

template <int line>
inline void log() {}

And then I try this trick to make using it easier:

#define LOG_LINE log<__LINE__>()

And then in a .cpp file I do:

void main()
{
    LOG_LINE;
}

And it seems that it works the way I'd like it to. I get the line from .cpp file, not the line at which LOG_LINE is declared in .h file. But I don't understand how it works. Does C++ perfrom double-pass preprocessing, leaving special macros like __LINE__ for second pass? Is this portable (standard) behavior? Should I expect this to work with all major C++ compilers? So far I've only tried MSVC.

like image 607
Violet Giraffe Avatar asked Dec 26 '22 12:12

Violet Giraffe


2 Answers

One should distinguish between the number of passes through the entire input, which is what terms like single-pass normally refer to, and handling of nested expansions. The preprocessor normally expands all macros in a single pass through the file, but it correctly expands the expanded forms, until there is nothing left to expand.

That is, LOG_LINE gets expanded to log<__LINE__>(), where __LINE__ again gets expanded to 3, producing the final expansion log<3>() — all in a single pass through the compilation unit.

like image 81
user4815162342 Avatar answered Jan 29 '23 02:01

user4815162342


Yes, this is portable, standard behaviour. Yes you can depend on it.

The reason is that the #define command simply stores the tokens that constitute the expansion text without interpreting it or expanding it at all. Because they are tokens, white space and comments are not stored.

Then when the macro name is used in the program text, it is replaced by the expansion text (and any arguments as needed). Then any tokens in the substituted text are scanned and replaced, and so on (except there is no recursive replacement).

In your case it takes two expansions to get to the underlying line number.

See N3797 16.3. It's relatively readable, for a standards document. There are examples quite close to what you're asking.

like image 45
david.pfx Avatar answered Jan 29 '23 04:01

david.pfx