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?
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
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.
In Visual Studio just surround it with _T(), for example:
TRACE( _T("function = %s"), _T(__FUNCTION__);
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.
For example use const auto name = L"" __FUNCTION__;
Related
I can find other questions on the site about using #if and #ifdef inside macros, and ways to get around the restriction to achieve various things, but none of them or their answers seem to match my use-case, which seems like an obvious one to me:
// the system flags are defined as object-like macros in this header...
#include <sys/stat.h>
// naive attempt at function-like macro that of course cannot work
#define MAYBE_EXPORT_FLAG(flag) \
#if defined(flag). \
exports.Set(Napi::String::New(env, #flag), \
Napi::Number::New(env, flag)); \
#endif
Napi::Object Init(Napi::Env env, Napi::Object exports) {
MAYBE_EXPORT_FLAG(UF_NODUMP)
MAYBE_EXPORT_FLAG(UF_IMMUTABLE)
MAYBE_EXPORT_FLAG(UF_APPEND)
return exports;
}
For instance, this previous question seems similar and a workaround is provided, but I couldn't adapt that set of macros to my case, or if it is adaptable I'm not understanding something there. In any case it doesn't use the macro's parameter in the generated code.
I did find that there were some tricks around to do what some of the other questions wanted but I couldn't find a way to adapt any of them to this case. But they are quite tricky. So is there some trick or is it simply impossible?
What you end up needing to do is define a macro for every symbol of interest that expands based on whether the symbol is defined:
#include <sys/stat.h>
#ifdef UF_NODUMP
#define IFDEF_UF_NODUMP(...) __VA_ARGS__
#else
#define IFDEF_UF_NODUMP(...)
#endif
#ifdef UF_IMMUTABLE
#define IFDEF_UF_IMMUTABLE(...) __VA_ARGS__
#else
#define IFDEF_UF_IMMUTABLE(...)
#endif
#ifdef UF_APPEND
#define IFDEF_UF_APPEND(...) __VA_ARGS__
#else
#define IFDEF_UF_APPEND(...)
#endif
#define MAYBE_EXPORT_FLAG(flag) \
IFDEF_ ## flag( \
exports.Set(Napi::String::New(env, #flag), \
Napi::Number::New(env, flag)); \
)
Napi::Object Init(Napi::Env env, Napi::Object exports) {
MAYBE_EXPORT_FLAG(UF_NODUMP)
MAYBE_EXPORT_FLAG(UF_IMMUTABLE)
MAYBE_EXPORT_FLAG(UF_APPEND)
return exports;
}
This is somewhat painful and repetitive, but you can put all the repeated stuff in its own header file somewhere that you don't need to refer to much. Depending on what you are are trying to do, you might find it useful to define IFNDEF_ macros for each symbol as well.
Here's an alternate approach, for interest (with a caveat--see bolded list entry). This doesn't use your MAYBE_EXPORT_FLAG skeleton, but:
It's a bit more generic (based on pattern matching)
Usage is less verbose than giant chains of conditional directives (detects undefined flags using pattern matching)
Works with identifier-like flags (anything right-pasteable to an identifier; includes positive decimals, octals, hex numbers)
Works with parenthetical flags
WILL NOT WORK for (non-parenthetical) "negative" flags (e.g., if your system defines a flag as #define FLAG -1)
Base macros
#define SECOND(...) SECOND_I(__VA_ARGS__,,)
#define SECOND_I(A,B,...) B
#define GLUE(A,B) GLUE_I(A,B)
#define GLUE_I(A,B) A##B
#define EAT(...)
#define IF_NMATCHES_USEABLE(P_, F_, M_) M_
#define IF_NMATCHES_P(...) , IF_NMATCHES_USEABLE
#define IF_NMATCHES_CALL(P_,F_,M_) \
SECOND(IF_NMATCHES_P F_, IF_NMATCHES_D2)(P_, F_, M_)
#define IF_NMATCHES_D2(P_,F_,M_) \
SECOND(GLUE(P_, F_), IF_NMATCHES_USEABLE)(P_, F_, M_)
#define MATCHED_PATTERN(P_, F_, M_) EAT
Usage
#include <sys/stat.h>
// Match macros (prefix plus flag)
#define STAT_FLAG_UF_NODUMP ,MATCHED_PATTERN
#define STAT_FLAG_UF_IMMUTABLE ,MATCHED_PATTERN
#define STAT_FLAG_UF_APPEND ,MATCHED_PATTERN
// Apply
#define EXPORT_FLAG(FLAG_) \
exports.Set(Napi::String::New(env, #FLAG_), \
Napi::Number::New(env, FLAG_));
Napi::Object Init(Napi::Env env, Napi::Object exports) {
IF_NMATCHES_CALL(STAT_FLAG_,UF_NODUMP,EXPORT_FLAG)(UF_NODUMP)
IF_NMATCHES_CALL(STAT_FLAG_,UF_IMMUTABLE,EXPORT_FLAG)(UF_IMMUTABLE)
IF_NMATCHES_CALL(STAT_FLAG_,UF_APPEND,EXPORT_FLAG)(UF_APPEND)
return exports;
}
Semantically, IF_NMATCHES_CALL takes as arguments a prefix, a flag, and the name of a function-like macro. It will expand to EAT if the pattern matches, or your function-like macro's name if it doesn't. Then you add call arguments; EAT is a variadic macro that swallows those arguments and expands to nothing... your macro does what you want.
A pattern is matched if there is a "pattern-match" macro; the pattern match macro has a name equivalent to the prefix and the flag you're checking, and a replacement list of ,MATCHED_PATTERN (comma is significant, see below).
Mechanism
The core here uses C preprocessor pattern matching via an indirect SECOND macro. By default this macro expands to its second argument; when used as a pattern matcher, you would arrange the first argument to produce a token to be matched; for match cases you define a macro with that name and put a comma in that macro's replacement list, which shifts in a non-default macro.
The top level macro first applies a pattern matcher on parenthesized flag replacement lists; in such cases, IF_NMATCHES_P will expand, shifting IF_NMATCHES_USEABLE. If the flag doesn't expand to a parenthesized list, the second level IF_NMATCHES_D2 is called. This call matches on the prefix/suffix combination (the GLUE here is what would fail if your system defined the flag as a negative literal, as e.g. -1 is not right-pasteable); if your flag is not defined, the result of this would be your match macro, which will shift in MATCHED_PATTERN resulting in the EAT. If your flag is defined, the argument is ignored by the SECOND macro resulting in IF_NMATCHES_USEABLE. IF_NMATCHES_USEABLE is what expands to M_.
Demo
http://coliru.stacked-crooked.com/a/d151d475f2736141
I am adding compile-time checks to my company's C++ projects to make sure the third-party libraries on all development machines and build servers are up-to-date. Most libraries define something like the following for e.g. version 3.1.4:
#define VERSION_MAJOR 3
#define VERSION_MINOR 1
#define VERSION_BUILD 4
This is nice and easy to check using static_assert or preprocessor directives.
Now I am looking at a third-party library that defines a single macro instead:
#define VERSION 3.1.4
How can I verify the value of such a macro at compile time?
With C++11, I could use a constexpr string comparison function, and stringify the macro to check it:
constexpr bool static_equal(const char * a, const char * b)
{
return (*a == *b) && (*a == '\0' || static_equal(a + 1, b + 1));
}
// stringification functions
#define str(x) #x
#define xstr(x) str(x)
static_assert(static_equal(xstr(VERSION), "3.1.4"), "incorrect version of libwhatever");
But we are using Visual Studio 2013 on the Windows machines, so I can only use the subset of C++11 that it supports. Unfortunately constexpr is not supported.
Here is what I am doing now:
#define str(x) #x
#define xstr(x) str(x)
#include xstr(libwhatever.version.is.VERSION.should.be.3.1.4)
Along with this, I add an empty file named libwhatever.version.is.3.1.4.should.be.3.1.4 to the project. So if the version is correct, the preprocessor will successfully include this file. Otherwise, it will fail with "Cannot open 'libwhatever.version.is.2.7.2.should.be.3.1.4', no such file or directory". And failing the build with a somewhat meaningful message is what counts in the end.
Of course this approach is not very flexible; for instance I cannot check for a minimal version, or a range of versions. But for me it is sufficient to be able to check the exact value.
This seems to work with Visual C++ as well as g++. I am not sure whether the behavior is entirely well-defined according to the standard, though.
You can't in the preprocessor, but you can abuse type traits!
VS 2013 seems to support variadic templates. Try using the macro CSTRING at https://stackoverflow.com/a/15912824/2097780 (you should be able to replace constexpr with const and have the code still work) and doing something like:
#define STRT(x) decltype(CSTRING(x))
static_assert(std::is_same<STRT(VERSION), STRT("3.1.4")>::value, "incorrect version of libwhatever");
EDIT: That doesn't work. However, if your compiler compiles this without errors:
extern const char data[] = "abc";
template <char C> struct x {
static const char c = C;
};
char buf[(int)x<"ABC123"[0]>::c];
int main() { return (int)buf; }
Then you can try this:
#include <type_traits>
#define VERSION 1.2.3
#define STR2(x) #x
#define STR(x) STR2(x)
template <char...> struct ststring;
// https://stackoverflow.com/a/15860416/2097780
#define MACRO_GET_1(str, i) \
(sizeof(str) > (i) ? str[(i)] : 0)
#define MACRO_GET_4(str, i) \
MACRO_GET_1(str, i+0), \
MACRO_GET_1(str, i+1), \
MACRO_GET_1(str, i+2), \
MACRO_GET_1(str, i+3)
#define MACRO_GET_16(str, i) \
MACRO_GET_4(str, i+0), \
MACRO_GET_4(str, i+4), \
MACRO_GET_4(str, i+8), \
MACRO_GET_4(str, i+12)
#define MACRO_GET_64(str, i) \
MACRO_GET_16(str, i+0), \
MACRO_GET_16(str, i+16), \
MACRO_GET_16(str, i+32), \
MACRO_GET_16(str, i+48)
#define MACRO_GET_STR(str) MACRO_GET_64(str, 0), 0
static_assert(std::is_same<ststring<MACRO_GET_STR(STR(VERSION))>,
ststring<MACRO_GET_STR("1.2.3")>>::value,
"invalid library version");
If you right click on your project->Properties->Build Events->Pre Build Event
You'll see an option that says "Command Line". You can put a call to another program here.
You could write another program in C++ or any language you prefer that checks your file (or any number of files you want) for "#define VERSION 3.1.4". You can abort your build and put any warnings you want in that program.
here is a tutorial: https://dillieodigital.wordpress.com/2012/11/27/quick-tip-aborting-builds-in-visual-studio-based-on-file-contents/
related reading: https://msdn.microsoft.com/en-us/library/e85wte0k.aspx
I tried messing with the preprocessor commands for a long time, and I couldn't find a way to do it using only preprocessor commands.
I understand the syntax of #define like,
#define Pi 3.14
So it's obvious that we can use Pi constant instead of 3.14 anywhere in code to make code more readable.
But I encountered a syntax like below.
Does it mean whenever I call the macro
doIT("hello world");
the code statements within {...} will be invoked ?
Does #define allow to give such syntax.?
What does the __FUNCTION__, __VA_ARGS__ mean ?
#define doIT(str, ...) \
{ \
if (pDoLog) pDoLog->LogMsg("[%s] Error: " str, LOG_WRONG, __FUNCTION__, ##__VA_ARGS__); \
printf("[%s] Error: " str "\n", __FUNCTION__, ##__VA_ARGS__); \
}
You don't "call" a macro, and its expansion doesn't get "invoked". The preprocessor just replaces the macro with its expansion, before the code gets compiled.
A macro defined with parentheses such as doIt(str) is a "function-like macro" which means it takes arguments which can be used in the expansion of the macro.
A function-like macro with ... in the argument list indicates it can accept a variable number of arguments. The special predefined symbol __VA_ARGS__ expands to the list of arguments passed to the ... placeholder.
__FUNCTION__ is a special predefined symbol that expands to the name of the current function being compiled, so wherever the macro gets expanded it will use the name of the enclosing function.
What does this mean?
#define __T(x) x
Just return x?
I am seeing code using syntax I've not seen before:
#define CREATE_ENCODER(CODEC) \
strcpy(codecName, __T(#CODEC); \
pCodec = new CODEC##VideoEncoder();
if(parFileName) \
{ pEncoderParams = new CODEC##EncoderParams; \
}
What is the # for?
Actually __T is used to turn string to wchar_t* or char*, in tchar.h you have:
#define __T(x) L ## x
used when UNICODE is enabled and
#define __T(x) x
when it is disabled
If your code is to be compiled on both UNICODE and non-UNICODE compilations you use:
TCHAR* sz = __T("My text");
most WINAPI functions use TCHAR* or some of its form
Actually I prefer _T() version, never knew __T version exists, at the bottom of tchar.h you have it defined:
#define _T(x) __T(x)
#define _TEXT(x) __T(x)
So back to your example:
strcpy(codecName, __T(#CODEC)); \
is equivalent to:
strcpy(codecName, "CODEC"); \
on NON-unicode build, and
strcpy(codecName, L"CODEC"); \
on UNICODE build
VERY IMPORTANT!!: using _T or __T is not really enough to make sure you code is UNICODE compilant. It will make it easier to call WINAPI functions. You must prepare your code to work with UNICODE.
Yes, that define is simply replaced with the passed value. This kind of define is often used if you e.g. want to determine at compile time if you want to pass a value through a translation function (#define __T(x) translate(x)) or not (#define __T(x) x).
# stringifies the passed value: http://gcc.gnu.org/onlinedocs/cpp/Stringizing.html and
## is the concatenation operator: http://gcc.gnu.org/onlinedocs/cpp/Concatenation.html
#include < iostream >
#define MY_CHK_DEF(flag) \
#ifdef (flag) \
std::cout<<#flag<<std::endl; \
#else \
std::cout<<#flag<<" ,flag not define"<<std::endl; \
#endif
int main()
{
MY_CHK_DEF(FLAG_1);
MY_CHK_DEF(FLAG_2);
MY_CHK_DEF(FLAG_3);
...
}
complier report:
main.cpp:3:24: error: '#' is not followed by a macro parameter
any ideas?
Thanks
You can't do it. #if, #else, and #endif must be the first tokens on the logical line. Your definition is just one logical line, so it doesn't work,
You have to do it the other way round(defining the macro for each #if/#ifdef/#else condition(if you nest you have to put a definition on each branch). You probably should define it at every logical branch or it will fail to compile when you try to adjust a rarely adjusted flag. You can #define noops like this. Note to be careful not to wrap expressions with side effects into #define 'd macros that reduce to a noop when the debug flag is on, or your program may not work right.
#define N(x)
#include < iostream >
#ifdef (flag)
#define MY_CHK_DEF(flag)
std::cout<<#flag<<std::endl;
#else
#define MY_CHK_DEF(flag) \
std::cout<<#flag<<" ,flag not define"<<std::endl;
#endif
int main()
{
MY_CHK_DEF(FLAG_1);
MY_CHK_DEF(FLAG_2);
MY_CHK_DEF(FLAG_3);
...
}
C preprocessor is single-pass and #define creates a pretty dumb replacement that isn't further processed - your MY_CHK_DEF(flag) macro inserts the #if statement inline into preprocessed code that is interpreted by C compiler and not valid C.
You can either rephrase it to be one-pass, or if you can't, run through preprocessor twice, manually - once through cpp -P and the second time through normal compilation process.
You actually can do this if you use BOOST processor header lib.. it provides a BOOST_PP_IF macro allow this type of decisions.
http://www.boost.org/doc/libs/1_53_0/libs/preprocessor/doc/ref/if.html