C++ concatenating __FILE__ and __LINE__ macros? - c++

I want my exception messages to contain info about the exception location.
So I would like to have some like thing this.
#define LOCATION __FILE__ " : " __LINE__
throw std::exception(std::string("ABCD. ") + LOCATION);
That define is obviously incorrect. How to achieve this?

You need to expand that macro in two levels:
#define S1(x) #x
#define S2(x) S1(x)
#define LOCATION __FILE__ " : " S2(__LINE__)
Here is the reason:
You need expand __LINE__ in two levels, before passing it to #x.
First of all, using operator # in a function-like macro, it has to be followed by a macro parameter but __LINE__ is not a parameter, so compiler complains it's a stray operator.
On the other hand, __LINE__ itself is a macro and contains current line number, it should be expanded to the number before using it with #, otherwise, you will get string "__LINE__" instead of a number.
Macro S2(__LINE__) expands __LINE__ to a line number, then we pass the line number to #x.

Related

macro expand in c++

Define two macros, as followed:
#define MACRO_COMBINE_INNER(A,B) A##B
#define MACRO_COMBINE(A,B) MACRO_COMBINE_INNER(A,B)
We use these macros
MACRO_COMBINE_INNER(ABC,__LINE__)
MACRO_COMBINE(ABC,__LINE__)
If the current line number is 123, that's LINE == 123, Why the results expand from the two macros are:
ABC__LINE__
ABC123
Order of expansion plays role here, first the outlier macro is expanded, then inner ones. In first case, after expanding MACRO_COMBINE_INNER you get:
ABC##__LINE__
which turns into ABC__LINE__, because __LINE__ is not a separate token here. In second case, preprocessor expands MACRO_COMBINE(ABC,__LINE__), then
__LINE__ is expanded. `
MACRO_COMBINE_INNER(ABC,123)
And then MACRO_COMBINE_INNER is expanded
ABC##123
There is similar behavior with stringify operator, which requires creating macro like this
#define STRINGIFY(x) #x
#define STRING(x) STRINGIFY(x)
To be able use __LINE__ in string literal:
#define THROW_BAD_INDEX(x) throw std::out_of_range \
(__FILE__ ":" STRING(__LINE__) ": Bad index")

C++ object-like macro containing URL interpreted as comment

Recently I run into strange behavior of my code:
#define STR(X) #X
#define XSTR(X) STR(X)
#define TEST_SERVER_HTTP http://host.cz/import.php
qDebug() << "Test server: " XSTR(TEST_SERVER_HTTP);
outputting just "http:" text.
I have figured out, that the "//" part of the URL is here interpreted as C++ comment, cutting the rest of URL text away.
Obvious workaround would be
#define TEST_SERVER_HTTP http:\/\/host.cz\/import.php
however I am getting (G++) warning
invalid string literal, ignoring final '\' [enabled by default]
wherever macro is used, even though the compiled code runs as expected.
Questions are:
Is there some "correct" way in C++ how to quote slash to suppress double slash meaning of start of comment ?
Is there some "canonical" workaround for putting URL constants as replace value of object-like macro ?
And no
#define TEST_SERVER_HTTP "http://host.cz/import.php"
is not acceptable for reasons given in the rest of my code.
It can be done easily, but you need to hack into it (as always):
#define STRINGIFY_(x) #x
#define STRINGIFY(x) STRINGIFY_(x)
#define SLASH() /
#define DOUBLE_SLASH() SLASH()SLASH()
#define STH_BEFORE() sth/before
#define STH_AFTER() sth/after
#define STH_DOUBLE_SLASH_STH STH_BEFORE()DOUBLE_SLASH()STH_AFTER()
int main()
{
//test
std::cout << STRINGIFY(STH_DOUBLE_SLASH_STH) << std::endl;
}
Output:
sth/before//sth/after
Usable new-macro-non-definiable version would be:
#define PLACEBO(x) x
#define STH_DOUBLE_SLASH_STH(x,y) PLACEBO(x)DOUBLE_SLASH()PLACEBO(y)
int main()
{
std::cout << STRINGIFY(STH_DOUBLE_SLASH_STH(before, after)) << std::endl;
}
Tested with MSVC 2015 and GCC 5.3.0.
Also note, that MSVC allows such comment (this is not sane!)
DOUBLE_SLASH() fun comment
You can't escape tokens in C/C++; the only place that backslash has an effect is inside string literals. Outside of a string literal (and when not part of a universal character name), a backslash is just a one-character token which is only valid during the preprocessing phases.
It is, however, easy enough to prevent multi-character tokens from being formed during the initial division of code into tokens, and you can do so without introducing whitespace. All you need is the identity macro:
#define I(X) X
Now you can use that to avoid the double slash becoming comments:
#define STR(X) #X
#define XSTR(X) STR(X)
#define TEST_SERVER_HTTP http:I(/)I(/)host.cz/import.php
qDebug() << "Test server: " XSTR(TEST_SERVER_HTTP);
There is no point using that on the single slash, or indeed any other character.
That solution will not, however, work to escape quotes and apostrophes (or whitespace, for that matter). As far as I know, there is no way to introduce an unmatched quote or apostrophe as a token.
Disclaimer: I didn't try that with MSVC, which is known to have a non-compliant preprocessor implementation. But it should work without issues on any standards-compliant implementation.

Different syntax for #define in C/C++ including many statements

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.

macro NAME expansion as string c/C++

I want use the NAME of the macro inside the macro expansion as string.
Example:
#define DEBUG_TEST(a, ...) printf("DEBUG_TEST::%s (%d) : " a, __FUNCTION__, __LINE__, ##__VA_ARGS__)
Want to change to something that doesn't need the "DEBUG_TEST" anymore in the exapansion, but something like:
#define DEBUG_TEST(a, ...) printf(__MACRO__ "::%s (%d) : " a, __FUNCTION__, __LINE__, ##__VA_ARGS__)
Of course in my example __MACRO__ dosen't exist...
I believe this is not possible. My suggestion would be to create another macro that takes the name of the macro as argument. Then use this macro in your other macroses.

Why would you use the __LINE__ macro in C++

I am trying to figure out how people use the __LINE__ macro at work. How do you guys use it?
You can use __LINE__, along with __FILE__, to report where problems occur in the source code.
Consider, for example, the assert() macro - this wording from the C99 standard, but C++ is similar, except it does not mention __func__:
When it is executed, if expression (which shall have a scalar type) is false (that is,
compares equal to 0), the assert macro writes information about the particular call that
failed (including the text of the argument, the name of the source file, the source line
number, and the name of the enclosing function — the latter are respectively the values of
the preprocessing macros __FILE__ and __LINE__ and of the identifier
__func__) on the standard error stream in an implementation-defined format.
#define assert(x) (void)(((x)==0)?_Assert(#x,__FILE__,__LINE__,__func__):0)
An even simpler example, here's a macro I occasionally use when all other forms of debugging have failed:
#define GOT_HERE std::cout << "At " __FILE__ ":" << __LINE__ << std::endl
Then when your code is mysteriously crashing and taking the device down with it, you can at least sprinkle this macro liberally into the source, in the hope that it will let you narrow down where the crash occurs (and after how many repeats). In practice you might not write to std::cout, but rather use the lowest-level, most reliable character output available on the platform.
I wrote a wrapper for malloc:
#if DEBUG
#define malloc(s) debugging_malloc(s, __FILE__, __LINE__)
#define free(p) debugging_free(p)
// Also, calloc(), strdup(), realloc() should be wrapped.
#endif // DEBUG
Within the wrapper, allocations are tracked according to the file and line number at which they occur. When the program exits, a utility functions outputs a list of any unfreed blocks.
If you are using gcc, it also gives you __FUNCTION__, which is really nice. C99-compliant compilers also have __func__, just as handy.
Most of the answers so far have involved some sort of debugging code. Another use of __LINE__ (and possibly __FILE__) is to enable a macro to generate a unique identifier each time it's called. This implementation of coroutines in C uses these macros to generate labels for a case statement, so it can jump to the last line you called yield from.
Just like this:
$ cat line.cc
#include <iostream>
int main(void) {
std::cout << "Hello, world from " << __LINE__ << std::endl;
return 0;
}
$ g++ -o line line.cc
$ ./line
Hello, world from 4
$
if (something truly impossible has happened) {
fprintf(stderr, "Value of PI less than 3 detected at %s line %d\n", __FILE__, __LINE__);
}
It's especially handy in CPP macros that detect intolerable conditions.
It's really just for debugging/logging purposes. I rarely use it because I tend to rely on debuggers like gdb more often.
But you could always use it when outputting debug information.
void dosomething(Object* o)
{
if (!o) {
std::cerr << __FILE__ << ":" << __LINE__ << ": o is NULL!\n";
abort();
}
}
Just to vaguely quote from the top of my head:
#define assert(e) ((e) ? (void)0 : printf("Assertion failed %s, %s : %s", #e, __FILE__, __LINE__))