17

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?
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • **See also:** http://stackoverflow.com/questions/4434282/visual-c-equivalent-of-file-line-and-pretty-function?rq=1 – Lightness Races in Orbit Jan 20 '13 at 04:24
  • I'm not aware of any that do it natively. Any chain that does would be chain-specific, to be sure, since the standard only calls for the "a character string literal" definition (§16.8) I think most of use have [found ways around it](http://stackoverflow.com/questions/13275015/c-preprocessor-literal-construction/13275048#13275048) and other string literal macro expansions to one degree or another =P – WhozCraig Jan 20 '13 at 05:57

5 Answers5

40

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
Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251
  • I am confused why three macros which is being called one after another? Shouldn't WIDE2 be just renamed as WFILE? [L##X](https://social.msdn.microsoft.com/Forums/en-US/abb44625-b178-4520-b8b9-c538d438097e/what-is-the-meaning-of-this-macro-define-tx-l-x?forum=vclanguage) – zar Nov 15 '17 at 16:48
  • 2
    @zar Try it and you'll find out why. – Mark Tolonen Nov 15 '17 at 16:52
  • 4
    @zar `WFILE` takes no parameters. You could do `WIDE1(__FILE__)` and it would work. `WIDE2(__FILE__)` by itself would generate `L__FILE__` which is an error. You need the double layer at least to expand the `__FILE__` macro, and the third layer is so you only have to type `WFILE`. – Mark Tolonen Nov 15 '17 at 18:04
  • Good to know, thanks because when it comes to working than even `_T(__FILE__)` also works for me as well but I am told it's not right solution. – zar Nov 15 '17 at 18:29
  • @zar: `_T` basically _is_ `WIDE1` – Lightness Races in Orbit Oct 29 '18 at 10:38
  • While this provides the current path of a file in wide characters, it doesn't work if the current file has non-ASCII characters (tested in MSVC 2019). – ScaledLizard Nov 03 '21 at 13:36
  • @ScaledLizard See update. You'll have to define "it doesn't work". – Mark Tolonen Nov 04 '21 at 16:30
  • Simply outputting WFILE to std::wcout didn't work for me, but your updated code works for me. I don't understand why it works though. Please explain: What encoding is used for __FILE__ then, and how does _setmode(_fileno(stdout), _O_U16TEXT) fix things? – ScaledLizard Nov 08 '21 at 09:38
  • @ScaledLizard `stdout` encodes output to the console encoding by default, which can’t handle most Unicode code points. Changing the mode to UTF-16 text fixes that. There was nothing wrong with WFILE itself. – Mark Tolonen Nov 08 '21 at 15:13
1

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.

doug65536
  • 6,562
  • 3
  • 43
  • 53
  • 2
    See the other answer. Macro expansion is suppressed before the `##` operator is applied so `_T(__FILE__)` will produce `L__FILE__`. Also, do not define a reserved name even to emulate another platform. Especially with only two characters — `_T` is likely to mean something else to another compiler. Better to `#define WIDEN _T` in order to have a non-reserved name across platforms. – Potatoswatter Jan 20 '13 at 09:03
  • @Potatoswatter Good catch. I recently touched this code, oops. – doug65536 Jan 20 '13 at 09:29
  • Yes I considered making up new names but why confuse the issue. People generally know what _T means and if you have a macro for it, go for it, else use L. – doug65536 Jan 20 '13 at 09:30
  • The answer before the example also needs to be fixed. Since I don't have Windows, I'm not sure how. Hmm, if that's the way `_T` is defined, I'm not sure why it would be considered a utility for general consumption. – Potatoswatter Jan 20 '13 at 09:30
  • Because `_T(__FILE__)` will expand to `L__FILE__`. – Potatoswatter Jan 20 '13 at 09:32
  • I've corrected that error and renamed the illegally named _T. Thanks! – doug65536 Jan 21 '13 at 01:02
  • Note that many programmers (well, at least me) try to avoid all that _T, TCHAR etc stuff that they see as legacy that deserves to die, though. (Because I think one should just use W APIs only in these days and not even bother with any of the "let the headers map FooBar to FooBarA or FooBarW" stuff. I wish there was a way to turn that off and have the headers just declare the W APIs only.) – tml May 07 '18 at 12:13
  • Me thinks, this `AssertBreakForce` is what actually `_ASSERTE` is. Available in `` – Chef Gladiator Mar 26 '20 at 12:58
0

In Visual Studio just surround it with _T(), for example:

TRACE( _T("function = %s"), _T(__FUNCTION__);
zar
  • 11,361
  • 14
  • 96
  • 178
0

I would have put this answer as a comment to an earlier reply but was not allowed due to not having the minimum 50 reputation to comment...

In Visual Studio, _T(__FILE__) will NOT expand to L__FILE__ unless you modify its standard definition of _T in the tchar.h header file. _T(__FILE__) and _T(__FUNCTION__) worked 5 years ago and still work today if you are looking for wide versions of the current file and function.

_T(x) is defined as __T(x), which is defined as L##x when _UNICODE is defined and x otherwise. So _T(__FILE__) expands to something like __T("my_file.c"), which then expands to L"my_file.c" or "my_file.c" depending on _UNICODE. It is useful to test things before claiming that they do not work.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Jim Monte
  • 91
  • 8
  • No idea who you're talking to here – Lightness Races in Orbit Feb 13 '18 at 20:01
  • What exactly do you not understand? – Jim Monte Feb 14 '18 at 16:04
  • The original question was if any major toolchain provide an equivalent to \__FILE__ with type wchar const[N]? In Visual Studio _T(\__FILE__) will produce a wide version of \_\_FILE\_\_. – Jim Monte Feb 14 '18 at 17:49
  • Then say that. This "answer" (which by your own admission is not one) seemed to be an attempt to respond to somebody about something somewhere else. – Lightness Races in Orbit Feb 14 '18 at 19:18
  • Indeed I would have liked to have put my answer in two comments since it explains to @zar why \_T(\_\_FILE\_\_) in Visual Studio works and why his TRACE() macro works. However, I made no admission that my answer was not one. In fact it is the only complete answer so far, giving both the major toolchain and its equivalent wide version that were requested in the question. Information in answers from MT and doug65536 are correct but not responsive to the question since they do not identify existing features in a toolchain. The answer by zar does not reference the \_\_FILE\_\_ macro. – Jim Monte Feb 14 '18 at 21:58
  • \_T(\_\_FILE\_\_) in MinGW using the definition of \_T(x) defined in their version of tchar.h (https://web.archive.org/web/20150123085928/https://sourceforge.net/p/mingw/mingw-org-wsl/ci/4.0.0/tree/include/tchar.h) is a related answer to this question. The internal macro name is different from the one in Visual Studio, but the effect is the same. – Jim Monte Feb 15 '18 at 16:59
-2

For example use const auto name = L"" __FUNCTION__;

zdf
  • 4,382
  • 3
  • 18
  • 29
  • Think you meant `wchar_t`, and this doesn't work, and it's the wrong macro. – Lightness Races in Orbit Dec 25 '18 at 23:33
  • Sorry for the typo. Between the quotation marks and __FUNCNAME__ is a space. Works nice in Visual Studio (e.g. version 2017). `code` – Big Steak On The Grill Dec 27 '18 at 14:58
  • Sorry for the typo. Between the quotation marks and __FUNCNAME__ is a space. Works nice in Visual Studio (e.g. version 2017). `#define __W_FUNCTION__ L"" __FUNCTION__`

    `const wchar_t *msg = L"" __FUNCTION__ ": one message.";`
    `const wchar_t *msg2 = __W_FUNCTION__ ": one more message.";`
    It uses the fact that adjacent string literals are concatenated by the compiler. (
    is a line break, which does not work on my computer).
    – Big Steak On The Grill Dec 27 '18 at 15:04
  • Although you're still talking about the wrong macro (I'm not asking about `__FUNCNAME__`, which is VS-only anyway), this [does appear to work](http://coliru.stacked-crooked.com/a/671acfc3400de89b). [Here's the standardese](http://eel.is/c++draft/lex.string#12): it seems ambiguous as to whether or not the result is implementation-defined, though. This could be the basis for a good answer though – Lightness Races in Orbit Dec 27 '18 at 15:10
  • I used `__FUNCTION__`. Your example `__FILE__`. Nevertheless my approach works nice with other predefined macros which are typical only provided as a const char[] (e.g. with the proposed define statement). I check your code piece in VS and it works there. If you do not mind, change the rating for the given solution. – Big Steak On The Grill Dec 27 '18 at 15:37
  • If you correct the wrong macro and give some reasoning as to why this is valid, well-defined and portable I'll be happy to! – Lightness Races in Orbit Dec 27 '18 at 15:41
  • For example use `const wchar_t *filename = L"" __FILE__;`. Better? – Big Steak On The Grill Dec 27 '18 at 15:47
  • Actually a good answer will be more than one sentence, and will contain some proof/reasoning, but thanks anyway – Lightness Races in Orbit Dec 27 '18 at 16:00