variable + value macro expansion - c++

I tried without any result.
My code looks like this:
#include "stdafx.h"
#include <iostream>
#define R() ( rand() )
#define H(a,b) ( a ## b )
#define S(a) ( # a )
#define CAT() H(S(distinct_name_), R())
int main(int argc, _TCHAR* argv[])
{
std::cout << CAT() << std::endl;
std::cout << CAT() << std::endl;
std::cout << CAT() << std::endl;
return 0;
}
I would like to get a result like this:
distinct_name_12233
distinct_name_147
distinct_name_435
as a result of concatenating
distinct_name_ (##) rand()
Right now I am getting an error:
term does not evaluate to a function taking 1 arguments.
Is this achievable ??
EDIT:
I finally succeeded after couple of hours. The preprocessor still does strange things I cannot understand completely. Here it goes:
#include "stdafx.h"
#include <iostream>
class profiler
{
public:
void show()
{
std::cout << "distinct_instance" << std::endl;
}
};
#define XX __LINE__
#define H(a,b) ( a ## b )
#define CAT(r) H(distinct_name_, r)
#define GET_DISTINCT() CAT(XX)
#define PROFILE() \
profiler GET_DISTINCT() ;\
GET_DISTINCT().show() ; \
int main(int argc, _TCHAR* argv[])
{
PROFILE()
PROFILE()
return 0;
}
And the output is:
distinct_instance
distinct_instance
Thanks #Kinopiko for __LINE__ hint. :)

No, you can't do that. Macros are a compile-time thing and functions are called only at run time, so there's no way you could get a random number from rand() into your macro expansion.

I see that a lot of people have already correctly answered this question, but as an alternative suggestion, if your preprocessor implements __TIME__ or __LINE__ you could get a result quite like what you want, with a line number or time concatenated, rather than a random number.

What you are actually getting is...
std::cout << distinct_name_rand() << std::endl;
distinct_name_rand() isn't a function, so it fails with a compile error.
Macros don't execute functions during compile time.

You must pass run-time computed value to the macro since macro are evaluated at compile-time.
Try:
#define H(a,b) ( a ## b )
#define S(a) ( # a )
#define CAT(r) H(S(distinct_name_), r)
std::cout << CAT(rand()) << std::endl;

Related

preventing unexpected macro re-expansion with boost? [duplicate]

This question already has answers here:
How do I temporarily disable a macro expansion in C/C++?
(6 answers)
Closed 5 years ago.
The goal here is to simply get a, b, c out instead of their actual values. The setup is "simple enough":
#include <boost/preprocessor/seq/for_each_i.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <iostream>
// Define "invalid" sequence first
#define SEQ (a)(b)(c)
// Try to create "final" value with `std::string("elem")`
// Brought in for explicit `std::string`, but no dice
#define MAKE_XSTRING(x) MAKE_STRING(x)
#define MAKE_STRING(x) std::string(#x)
// oh, the humanity! vvvvvvvvvvvv or BOOST_PP_STRINGIZE
#define HUMANIZE(r, data, elem) (MAKE_XSTRING(elem))
#define SEQ_HUMAN BOOST_PP_SEQ_FOR_EACH(HUMANIZE,,SEQ)
So what I'm expecting at this point is what I have: a new sequence with (std::string("a")) etc:
// confirmation: vvvvvvvvvvvvvvvv
// warning: Humans: (std::string("a")) (std::string("b")) (std::string("c"))
#pragma message "Humans: " BOOST_PP_STRINGIZE(SEQ_HUMAN)
Thinking I'm so very clever and have gotten my values sorted out in some explicit strings, now I define the actual values for what the "real" code needs.
// Now that we have the "final" values, actually define the real values
// in real code, it's some lengthy nested namespaces (inconvenient to type)
#define a 123
#define b 456
#define c 789
And at long last, lets print them to make sure they aren't expanded:
// Let there be printing!
#define GOTTA_PRINT_EM_ALL(r,data,i,elem) << ((i)+1) << ". " << elem << std::endl
int main(int argc, const char **argv) {
std::cout << "Humans: " << std::endl
BOOST_PP_SEQ_FOR_EACH_I(GOTTA_PRINT_EM_ALL,,SEQ_HUMAN);
}
But it seems the aliens did indeed take over:
Humans:
1. 123
2. 456
3. 789
Given that they're supposed to be std::string("a")...how the heck are the real values getting back in there?! I thought maybe the ("a") from the std::string constructor was creating issues, but it doesn't seem so (BOOST_PP_STRINGIZE results in same behavior). Any suggestions?
The macro indeed expands into code tokens:
test.cpp|24 col 1| note: #pragma message: Humans: (std::string("123")) (std::string("456")) (std::string("789"))
Now when you insert the code tokens into your GOTTA_PRINT_EM_ALL macro, you get
<< ((0)+1) << ". " << std::string(\"123\") << std::endl << ((1)+1) << ". " << std::string(\"456\") << std::endl << ((2)+1) << ". << std::string(\"789\")" << std::endl
Completely expectedly printing
Humans:
1. 123
2. 456
3. 789
To get the "code tokens" you need to stringize them as well:
// Let there be printing!
#define GOTTA_PRINT_EM_ALL(r,data,i,elem) << ((i)+1) << ". " << BOOST_PP_STRINGIZE(elem) << std::endl
Printing
Humans:
1. std::string("123")
2. std::string("456")
3. std::string("789")
See it Live On Coliru
#include <boost/preprocessor/seq/for_each_i.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <iostream>
#include <string>
#define a 123
#define b 456
#define c 789
#define SEQ (a)(b)(c)
// Try to create "final" value with `std::string("elem")`
// Brought in for explicit `std::string`, but no dice
#define MAKE_STRING(x) std::string(#x)
#define MAKE_XSTRING(x) MAKE_STRING(x)
#define HUMANIZE(r, data, elem) (MAKE_XSTRING(elem))
#define SEQ_HUMAN BOOST_PP_SEQ_FOR_EACH(HUMANIZE,,SEQ)
// Let there be printing!
#define GOTTA_PRINT_EM_ALL(r,data,i,elem) << ((i)+1) << ". " << BOOST_PP_STRINGIZE(elem) << std::endl
int main() {
std::cout << "Humans: " << std::endl
BOOST_PP_SEQ_FOR_EACH_I(GOTTA_PRINT_EM_ALL,,SEQ_HUMAN);
}

c++ get macro name in macro

How to get the macro name inside a macro?
Say we have:
#include <iostream>
using std::cout;
using std::endl;
#define MACRO() \
cout << __MACRO_NAME__ << endl
int main () {
MACRO();
return 0;
}
Expected output:
MACRO
Did little bit of research and I don't think that is doable in c++.
But you could use this:
#define MACRO2(x) cout << #x << endl
#define MACRO MACRO2(MACRO)
In this you can use MACRO2 to do the task of MACRO and you can also access name of MACRO as an argument x.

C++ compile time counter in macros

I am trying to achieve the following but in a way that follows the c++ standard :
#include <iostream>
using namespace std;
#define MAKE_BOTH(MAKE_FUNC) \
MAKE_FUNC(FIRST) \
MAKE_FUNC(SECOND) \
MAKE_FUNC(THIRD) \
MAKE_FUNC(FOURTH)
#define MAKE_STRINGS(NAME) #NAME,
const char* genericString[] {
MAKE_BOTH(MAKE_STRINGS)
};
#define MAKE_ENUM(NAME) NAME = (1L << __COUNTER__),
enum genericEnum {
MAKE_BOTH(MAKE_ENUM)
};
int main()
{
cout << FIRST << endl;
cout << SECOND << endl;
cout << THIRD << endl;
cout << FOURTH << endl;
}
If you think a while about this code, this creates both, enums and array of "strings" which consists of the same names as enums. The examle code expands to :
const char* genericString[] {
"FIRST",
"SECOND",
"THIRD",
"FOURTH"
};
enum genericEnum {
FIRST = 1L << 0; (1)
SECOND = 1L << 1; (2)
THIRD = 1L << 2; (4)
FOURTH = 1L << 3; (8)
};
Basically the enums are assigned power of 2 values, the question is - is there a relatively simple way of achieving the same thing without using COUNTER ?
The problem is similar to this one:
Counting preprocessor macros
but I have to increase the value of counter each time the macro is used at compile time, I could not figure out how to do it without using the non-standard COUNTER macro.
Please beware the c++ 11 is not an option, but using boost is, I tried the boost approach as well but it is not possible to call the #include directive by a macro which unables me from incrementing the boost preprocessor counter.
You may generate something like this:
enum genericEnum
{
MY_ENUM_BASE=0,
FIRST,
PAST_FIRST= (FIRST<<1)-1,
SECOND,
PAST_SECOND= (SECOND<<1)-1,
THIRD,
PAST_THIRD= (THIRD<<1)-1,
FOURTH,
PAST_FOURTH= (FOURTH<<1)-1,
};
using standard macroprocessor without using COUNTER,
i.e. defining MAKE_ENUM as
#define MAKE_ENUM(NAME) NAME, PAST##_NAME= (NAME<<1)-1,

Determining calling line without macro

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.
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.
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.
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>

Adding message to assert

I'm looking for a way to add custom messages to assert statements.
I found this questions Add custom messages in assert? but the message is static there. I want to do something like this:
assert((0 < x) && (x < 10), std::string("x was ") + myToString(x));
When the assertion fails I want the normal output plus for example "x was 100".
You are out of luck here. The best way is to define your own assert macro.
Basically, it can look like this:
#ifndef NDEBUG
# define ASSERT(condition, message) \
do { \
if (! (condition)) { \
std::cerr << "Assertion `" #condition "` failed in " << __FILE__ \
<< " line " << __LINE__ << ": " << message << std::endl; \
std::terminate(); \
} \
} while (false)
#else
# define ASSERT(condition, message) do { } while (false)
#endif
This will define the ASSERT macro only if the no-debug macro NDEBUG isn’t defined.
Then you’d use it like this:
ASSERT((0 < x) && (x < 10), "x was " << x);
Which is a bit simpler than your usage since you don’t need to stringify "x was " and x explicitly, this is done implicitly by the macro.
There are some old tricks to include messages without writing your own routines:
The first is this:
bool testbool = false;
assert(("this is the time", testbool));
There is also:
bool testbool = false;
assert(testbool && "This is a message");
The first one works, because the inside parens expression result is the value of 'testbool'.
The second one works, because the value of the string is going to be non-zero.
A better alternative is to teach the debugger to stop on assert when it fails, then you could examine not only the x value but any other information including call stack. Perhaps, this is what you are really looking for.
Sample implementation is mentioned here Ways to show your co-programmers that some methods are not yet implemented in a class when programming in C++
#define ASSERT_WITH_MESSAGE(condition, message) do { \
if (!(condition)) { printf((message)); } \
assert ((condition)); } while(false)
Extending on Kondrad Rudolph's answer:
#include <iostream>
#ifdef NDEBUG
#define assert(condition, message) 0
#else
#define assert(condition, message)\
(!(condition)) ?\
(std::cerr << "Assertion failed: (" << #condition << "), "\
<< "function " << __FUNCTION__\
<< ", file " << __FILE__\
<< ", line " << __LINE__ << "."\
<< std::endl << message << std::endl, abort(), 0) : 1
#endif
void foo() {
int sum = 0;
assert((sum = 1 + 1) == 3, "got sum of " << sum << ", but expected 3");
}
int main () {
foo();
}
Output is...
Assertion failed: ((sum = 1 + 1) == 3), function foo, file foo.cpp, line 13.
got sum of 2, but expected 3
zsh: abort ./a.out
which is similar to what the std::assert macro outputs on my system just with the additional user defined message
For the sake of completeness, I published a drop-in 2 files assert macro implementation in C++:
#include <pempek_assert.h>
int main()
{
float min = 0.0f;
float max = 1.0f;
float v = 2.0f;
PEMPEK_ASSERT(v > min && v < max,
"invalid value: %f, must be between %f and %f", v, min, max);
return 0;
}
Will prompt you with:
Assertion 'v > min && v < max' failed (DEBUG)
in file e.cpp, line 8
function: int main()
with message: invalid value: 2.000000, must be between 0.000000 and 1.000000
Press (I)gnore / Ignore (F)orever / Ignore (A)ll / (D)ebug / A(b)ort:
Where
(I)gnore: ignore the current assertion
Ignore (F)orever: remember the file and line where the assertion fired and
ignore it for the remaining execution of the program
Ignore (A)ll: ignore all remaining assertions (all files and lines)
(D)ebug: break into the debugger if attached, otherwise abort() (on Windows,
the system will prompt the user to attach a debugger)
A(b)ort: call abort() immediately
You can find out more about it there:
blog post
GitHub project
Hope that helps.
Yes, this is possible.
To enable expression like better_assert((0 < x) && (x < 10), std::string("x was ") + myToString(x));, we are supposed to have a corresponding macro in a form of
#define better_assert(EXPRESSION, ... ) ((EXPRESSION) ? \
(void)0 : print_assertion(std::cerr, \
"Assertion failure: ", #EXPRESSION, " in File: ", __FILE__, \
" in Line: ", __LINE__ __VA_OPT__(,) __VA_ARGS__))
in which print_assertion is a proxy function to do the assertion. When the EXPRESSION is evaluated false, all the debug information, the __VA_ARGS__, will be dumped to std::cerr. This function takes arbitrary numbers of arguments, thus we should implement a variadic templated function:
template< typename... Args >
void print_assertion(std::ostream& out, Args&&... args)
{
out.precision( 20 );
if constexpr( debug_mode )
{
(out << ... << args) << std::endl;
abort();
}
}
In the previous implementation, the expression (out << ... << args) << std::endl; make use of fold expression in C++17 (https://en.cppreference.com/w/cpp/language/fold); the constant expression debug_mode is related to the compilation options passed, which is can be defined as
#ifdef NDEBUG
constexpr std::uint_least64_t debug_mode = 0;
#else
constexpr std::uint_least64_t debug_mode = 1;
#endif
It also worth mentioning that the expression if constexpr( debug_mode ) makes use of constexpr if (https://en.cppreference.com/w/cpp/language/if) imported since C++17.
To wrap everything up, we have:
#ifdef NDEBUG
constexpr std::uint_least64_t debug_mode = 0;
#else
constexpr std::uint_least64_t debug_mode = 1;
#endif
template< typename... Args >
void print_assertion(std::ostream& out, Args&&... args)
{
out.precision( 20 );
if constexpr( debug_mode )
{
(out << ... << args) << std::endl;
abort();
}
}
#ifdef better_assert
#undef better_assert
#endif
#define better_assert(EXPRESSION, ... ) ((EXPRESSION) ? (void)0 : print_assertion(std::cerr, "Assertion failure: ", #EXPRESSION, " in File: ", __FILE__, " in Line: ", __LINE__ __VA_OPT__(,) __VA_ARGS__))
A typical test case demonstrating its usage can be:
double const a = 3.14159265358979;
double const b = 2.0 * std::asin( 1.0 );
better_assert( a==b, " a is supposed to be equal to b, but now a = ", a, " and b = ", b );
This will produce something error message like:
Assertion failure: a==b in File: test.cc in Line: 9 a is supposed to be equal to b, but now a = 3.1415926535897900074 and b = 3.141592653589793116
[1] 8414 abort (core dumped) ./test
And the full source code is available in this repo: https://github.com/fengwang/better_assert
To take on Feng Wang answer, in newer versions of C++, anything inline is going to be optimized out. So you can have an inline function in a header file which does all the work.
inline constexpr void NOT_USED()
{
}
template <class T, class ...ARGS>
inline constexpr void NOT_USED(T && first, ARGS && ...args)
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-result"
static_cast<void>(first);
#pragma GCC diagnostic pop
NOT_USED(args...);
}
template<typename ... ARGS>
void SAFE_ASSERT(bool test_result, ARGS &&... args)
{
#ifdef _DEBUG
if(test_result)
{
(std::cerr << ... << args) << std::endl;
abort();
}
#else
NOT_USED(test_result, args...);
#endif
}
Some comments:
If _DEBUG is not defined, the function becomes empty so it can be optimized out 100%
If you call the function with a side effect, the non-debug code still works:
my_assert(c++ < --z, "the #define versions do not behave similarly");
These side effects are clearly visible here. However, if you call a function, it could be really difficult to know whether something happens in the function which was not otherwise expected.
There are ways to prevent such side effects from happening, though (Example). But all in all, in some cases, you need to call a function for the test and it may have a side effect and therefore needs to not be optimized out in non-debug code.
I use abort() because I know that stops the debugger properly, std::terminate() is the C++ way which in modern systems does the same thing, but if std::terminate() doesn't work for your debugger the abort() will.
The NOT_USED() is to avoid warnings about unused function parameters (if you don't have that warning, you may end up with expected bugs).
I have an implementation in snapdev: see safe_assert.h and not_used.h.
going along with Konrad Rudolf's answer you can do it a bit more concise with
#include <assert.h>
#include <stdio.h>
#define ASSERT(condition,...) assert( \
condition|| \
(fprintf(stderr,__VA_ARGS__)&&fprintf(stderr," at %s:%d\n",__FILE__,__LINE__)) \
);
which also works in C,
it works using the general idea from some of the answers to the question you linked, but the macro allows it to be a little more flexible