3

Is it possible to determine the line number that calls a function without the aid of a macro?

Consider this code:

#include <iostream>

#define PrintLineWithMacro() \
  std::cout << "Line: " << __LINE__ << std::endl;   // Line 4

void PrintLine()
{
  std::cout << "Line: " << __LINE__ << std::endl;   // Line 8
}

int main(int argc, char **argv)
{
  PrintLine();           // Line 13
  PrintLineWithMacro();  // Line 14
  return 0;
}

which outputs the following:

Line: 8
Line: 14

I understand why each prints what they do. I am more interested if it's possible to mimic the macro function without using a macro.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
elmt
  • 1,604
  • 14
  • 24
  • 3
    The only way to get the line is with `__LINE__`; you have to use the preprocessor somewhere. (In other words, the preprocessor deals with raw *code*, and line numbers are part of raw *code*.) – GManNickG Oct 27 '10 at 01:20

3 Answers3

6

I would do the following:

#define PrintLine() PrintLine_(__LINE__)

void PrintLine_(int line) {
    std::cout << "Line: " << line << std::endl;
}

I know that this doesn't completely remove the preprocessor, but it does move most of the logic into an actual function.

Bill Lynch
  • 80,138
  • 16
  • 128
  • 173
  • 3
    This is a decent workaround, because you *have* to use a macro. However, you should explicitly qualify the function call in the macro (::PrintLine_, or whichever namespace it's in) and use parentheses. –  Oct 27 '10 at 01:28
2

C++ has caught up with this question in the c++20 standard.

In c++20 you may now do:

#include <iostream>
#include <source_location>

void PrintLine(std::source_location location = std::source_location::current())
{
    std::cout << "Line: " << location.line() << std::endl;   // Line 8
}

int main(int argc, char **argv)
{
    PrintLine();           // Line: 11
    PrintLine();           // Line: 12
    return 0;
}

Another question is whether the compiler of your interest has caught up with the standard. Note that the construct was present pre c++20 and you could try:

#include <experimental/source_location>
gg99
  • 445
  • 6
  • 12
1

Not portably. On any given platform, you could basically re-implement the details of a debugger - the information is effectively stored on your stack as the return address. You can get at that kind of thing with the backtrace() function on some platforms.

xscott
  • 2,350
  • 16
  • 18