Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there widely-available wide-character variant of `__FILE__`?

Tags:

c++

One may generally use __LINE__ and __FILE__ in C++ programs, with many toolchains, including GCC.

__LINE__ under GCC evaluates to an expression of type int;
__FILE__ evaluates to a char const[N] where N is the appropriate value.

  • Does any major toolchain provide an equivalent to __FILE__ with type wchar const[N]?
  • If so, what is it?
like image 722
Lightness Races in Orbit Avatar asked Jan 20 '13 04:01

Lightness Races in Orbit


2 Answers

You can make your own WFILE:

#define WIDE2(x) L##x
#define WIDE1(x) WIDE2(x)
#define WFILE WIDE1(__FILE__)

Tested with non-ASCII characters and filename 马克.cpp:

#include <stdio.h>
#include <io.h>
#include <fcntl.h>

#define WIDE2(x) L##x
#define WIDE1(x) WIDE2(x)
#define WFILE WIDE1(__FILE__)

int main() {
    _setmode(_fileno(stdout), _O_U16TEXT); // required for Unicode output to console
    wprintf(L"%s\n", WFILE);
}

Demo (running from cmd.exe and Chinese language support installed):

C:\>cl /W4 /nologo 马克.cpp
马克.cpp

C:\>马克.exe
马克.cpp
like image 118
Mark Tolonen Avatar answered Nov 15 '22 11:11

Mark Tolonen


Use:

WIDE(MEXPAND(__FILE__))

and

WIDE(STRINGIFY(__LINE__))

or replace __LINE__ with anything that needs to be stringified, and replace __FILE__ with any macro string literal you want to widen.

Using the following definitions:

#define STRINGIFY2(m) #m
#define MEXPAND(m) m
#define STRINGIFY(m) STRINGIFY2(m)
#define WIDE(m) L ## m

Example usage:

#define AssertBreakMethod DebugBreak

#define AssertBreakForce(expr) \
  do \
  { \
    if (!(expr)) \
    { \
      OutputDebugStringW(WIDE(MEXPAND(__FILE__)) \
          WIDE("(") WIDE(STRINGIFY(__LINE__)) \
          WIDE("): Assertion failed: ") \
          WIDE(#expr) WIDE("\n")); \
      AssertBreakMethod(); \
    } \
  } \
  while (0)

Note that the whole parameter to OutputDebugString is assembled statically at compile time into a single string literal.

The trick with stringification of a macro is passing it through another macro. When __FILE__ is passed to MEXPAND it is expanded at that time. MEXPAND returns its argument which is now a string. It is then legal to put the leading L there to make it wide.

STRINGIFY does the same trick, it passes its argument through STRINGIFY2 which expands the argument to the line number (which looks like an integer at that point) then STRINGIFY2 puts the # symbol before it, stringifying the integer.

like image 1
doug65536 Avatar answered Nov 15 '22 12:11

doug65536