Let's say that for some reason you need to write a macro: MACRO(X,Y). (Let's assume there's a good reason you can't use an inline function.) You want this macro to emulate a call to a function with no return value.
Example 1: This should work as expected.
if (x > y)
MACRO(x, y);
do_something();
Example 2: This should not result in a compiler error.
if (x > y)
MACRO(x, y);
else
MACRO(y - x, x - y);
Example 3: This should not compile.
do_something();
MACRO(x, y)
do_something();
The naïve way to write the macro is like this:
#define MACRO(X,Y) \
cout << "1st arg is:" << (X) << endl; \
cout << "2nd arg is:" << (Y) << endl; \
cout << "Sum is:" << ((X)+(Y)) << endl;
This is a very bad solution which fails all three examples, and I shouldn't need to explain why.
Ignore what the macro actually does, that's not the point.
Now, the way I most often see macros written is to enclose them in curly braces, like this:
#define MACRO(X,Y) \
{ \
cout << "1st arg is:" << (X) << endl; \
cout << "2nd arg is:" << (Y) << endl; \
cout << "Sum is:" << ((X)+(Y)) << endl; \
}
This solves example 1, because the macro is in one statement block. But example 2 is broken because we put a semicolon after the call to the macro. This makes the compiler think the semicolon is a statement by itself, which means the else statement doesn't correspond to any if statement! And lastly, example 3 compiles OK, even though there is no semicolon, because a code block doesn't need a semicolon.
Is there a way to write a macro so that it pass all three examples?
Note: I am submitting my own answer as part of the accepted way of sharing a tip, but if anyone has a better solution feel free to post it here, it may get more votes than my method. :)
There is a rather clever solution:
#define MACRO(X,Y) \
do { \
cout << "1st arg is:" << (X) << endl; \
cout << "2nd arg is:" << (Y) << endl; \
cout << "Sum is:" << ((X)+(Y)) << endl; \
} while (0)
Now you have a single block-level statement, which must be followed by a semicolon. This behaves as expected and desired in all three examples.
Macros should generally be avoided; prefer inline functions to them at all times. Any compiler worth its salt should be capable of inlining a small function as if it were a macro, and an inline function will respect namespaces and other scopes, as well as evaluating all the arguments once.
If it must be a macro, a while loop (already suggested) will work, or you can try the comma operator:
#define MACRO(X,Y) \
( \
(cout << "1st arg is:" << (X) << endl), \
(cout << "2nd arg is:" << (Y) << endl), \
(cout << "3rd arg is:" << ((X) + (Y)) << endl), \
(void)0 \
)
The (void)0 causes the statement to evaluate to one of void type, and the use of commas rather than semicolons allows it to be used inside a statement, rather than only as a standalone. I would still recommend an inline function for a host of reasons, the least of which being scope and the fact that MACRO(a++, b++) will increment a and b twice.
I know you said "ignore what the macro does", but people will find this question by searching based on the title, so I think discussion of further techniques to emulate functions with macros are warranted.
Closest I know of is:
#define MACRO(X,Y) \
do { \
auto MACRO_tmp_1 = (X); \
auto MACRO_tmp_2 = (Y); \
using std::cout; \
using std::endl; \
cout << "1st arg is:" << (MACRO_tmp_1) << endl; \
cout << "2nd arg is:" << (MACRO_tmp_2) << endl; \
cout << "Sum is:" << (MACRO_tmp_1 + MACRO_tmp_2) << endl; \
} while(0)
This does the following:
Works correctly in each of the stated contexts.
Evaluates each of its arguments exactly once, which is a guaranteed feature of a function call (assuming in both cases no exceptions in any of those expressions).
Acts on any types, by use of "auto" from C++0x. This is not yet standard C++, but there's no other way to get the tmp variables necessitated by the single-evaluation rule.
Doesn't require the caller to have imported names from namespace std, which the original macro does, but a function would not.
However, it still differs from a function in that:
In some invalid uses it may give different compiler errors or warnings.
It goes wrong if X or Y contain uses of 'MACRO_tmp_1' or 'MACRO_tmp_2' from the surrounding scope.
Related to the namespace std thing: a function uses its own lexical context to look up names, whereas a macro uses the context of its call site. There's no way to write a macro that behaves like a function in this respect.
It can't be used as the return expression of a void function, which a void expression (such as the comma solution) can. This is even more of an issue when the desired return type is not void, especially when used as an lvalue. But the comma solution can't include using declarations, because they're statements, so pick one or use the ({ ... }) GNU extension.
Here is an answer coming right from the libc6!
Taking a look at /usr/include/x86_64-linux-gnu/bits/byteswap.h, I found the trick you were looking for.
A few critics of previous solutions:
Kip's solution does not permit evaluating to an expression, which is in the end often needed.
coppro's solution does not permit assigning a variable as the expressions are separate, but can evaluate to an expression.
Steve Jessop's solution uses the C++11 auto keyword, that's fine, but feel free to use the known/expected type instead.
The trick is to use both the (expr,expr) construct and a {} scope:
#define MACRO(X,Y) \
( \
{ \
register int __x = static_cast<int>(X), __y = static_cast<int>(Y); \
std::cout << "1st arg is:" << __x << std::endl; \
std::cout << "2nd arg is:" << __y << std::endl; \
std::cout << "Sum is:" << (__x + __y) << std::endl; \
__x + __y; \
} \
)
Note the use of the register keyword, it's only a hint to the compiler.
The X and Y macro parameters are (already) surrounded in parenthesis and casted to an expected type.
This solution works properly with pre- and post-increment as parameters are evaluated only once.
For the example purpose, even though not requested, I added the __x + __y; statement, which is the way to make the whole bloc to be evaluated as that precise expression.
It's safer to use void(); if you want to make sure the macro won't evaluate to an expression, thus being illegal where an rvalue is expected.
However, the solution is not ISO C++ compliant as will complain g++ -pedantic:
warning: ISO C++ forbids braced-groups within expressions [-pedantic]
In order to give some rest to g++, use (__extension__ OLD_WHOLE_MACRO_CONTENT_HERE) so that the new definition reads:
#define MACRO(X,Y) \
(__extension__ ( \
{ \
register int __x = static_cast<int>(X), __y = static_cast<int>(Y); \
std::cout << "1st arg is:" << __x << std::endl; \
std::cout << "2nd arg is:" << __y << std::endl; \
std::cout << "Sum is:" << (__x + __y) << std::endl; \
__x + __y; \
} \
))
In order to improve my solution even a bit more, let's use the __typeof__ keyword, as seen in MIN and MAX in C:
#define MACRO(X,Y) \
(__extension__ ( \
{ \
__typeof__(X) __x = (X); \
__typeof__(Y) __y = (Y); \
std::cout << "1st arg is:" << __x << std::endl; \
std::cout << "2nd arg is:" << __y << std::endl; \
std::cout << "Sum is:" << (__x + __y) << std::endl; \
__x + __y; \
} \
))
Now the compiler will determine the appropriate type. This too is a gcc extension.
Note the removal of the register keyword, as it would the following warning when used with a class type:
warning: address requested for ‘__x’, which is declared ‘register’ [-Wextra]
C++11 brought us lambdas, which can be incredibly useful in this situation:
#define MACRO(X,Y) \
[&](x_, y_) { \
cout << "1st arg is:" << x_ << endl; \
cout << "2nd arg is:" << y_ << endl; \
cout << "Sum is:" << (x_ + y_) << endl; \
}((X), (Y))
You keep the generative power of macros, but have a comfy scope from which you can return whatever you want (including void). Additionally, the issue of evaluating macro parameters multiple times is avoided.
Create a block using
#define MACRO(...) do { ... } while(false)
Do not add a ; after the while(false)
Your answer suffers from the multiple-evaluation problem, so (eg)
macro( read_int(file1), read_int(file2) );
will do something unexpected and probably unwanted.
As others have mentioned, you should avoid macros whenever possible. They are dangerous in the presence of side effects if the macro arguments are evaluated more than once. If you know the type of the arguments (or can use C++0x auto feature), you could use temporaries to enforce single evaluation.
Another problem: the order in which multiple evaluations happen may not be what you expect!
Consider this code:
#include <iostream>
using namespace std;
int foo( int & i ) { return i *= 10; }
int bar( int & i ) { return i *= 100; }
#define BADMACRO( X, Y ) do { \
cout << "X=" << (X) << ", Y=" << (Y) << ", X+Y=" << ((X)+(Y)) << endl; \
} while (0)
#define MACRO( X, Y ) do { \
int x = X; int y = Y; \
cout << "X=" << x << ", Y=" << y << ", X+Y=" << ( x + y ) << endl; \
} while (0)
int main() {
int a = 1; int b = 1;
BADMACRO( foo(a), bar(b) );
a = 1; b = 1;
MACRO( foo(a), bar(b) );
return 0;
}
And it's output as compiled and run on my machine:
X=100, Y=10000, X+Y=110
X=10, Y=100, X+Y=110
If you're willing to adopt the practice of always using curly braces in your if statements,
Your macro would simply be missing the last semicolon:
#define MACRO(X,Y) \
cout << "1st arg is:" << (X) << endl; \
cout << "2nd arg is:" << (Y) << endl; \
cout << "Sum is:" << ((X)+(Y)) << endl
Example 1: (compiles)
if (x > y) {
MACRO(x, y);
}
do_something();
Example 2: (compiles)
if (x > y) {
MACRO(x, y);
} else {
MACRO(y - x, x - y);
}
Example 3: (doesn't compile)
do_something();
MACRO(x, y)
do_something();
Related
I want to write a macros to print pairs of {variable name, variable value}. The variables are supposed to be arguments of variadic macros.
I made a simple code, that produces compilation error: "expected expression" in cases when number of variables to print is less than maximum possible number.
#define IS_EMPTY(...) ( sizeof( (char[]){#__VA_ARGS__} ) == 1 )
#define PRINT_VAR(x) std::cout << "\"" << #x << "\": " << (x) << " ";
#define PRINT_VARS3(x, ...) {PRINT_VAR(x); }
#define PRINT_VARS2(x, ...) {PRINT_VAR(x); \
if constexpr (not IS_EMPTY(__VA_ARGS__)) PRINT_VARS3(__VA_ARGS__); }
#define PRINT_VARS1(x, ...) {PRINT_VAR(x); \
if constexpr (not IS_EMPTY(__VA_ARGS__)) PRINT_VARS2(__VA_ARGS__); }
#define PRINT_VARS(x, ...) {PRINT_VAR(x); \
if constexpr (not IS_EMPTY(__VA_ARGS__)) {\
PRINT_VARS1(__VA_ARGS__); \
} \
std::cout << "\n";}
int i = 100;
float j = 200.5;
int k = 300;
float l = -0.576f;
PRINT_VARS(i, j, k, l); // works fine
//PRINT_VARS(i, j); // compilation error
Thing that I cant understand, if I remove << (x) from second line, PRINT_VARS work with different number of arguments.
What is the reason and how to fix it?
Thank you!
Removing << (x) from the second line makes code compliable and working except it cant printout the variables values.
I expect the compiler not to check if constexpr branches at 0 condition. But it looks like empty
VA_ARGS passed to PRINT_VAR macros that leads to this error.
I have tried this code with gcc12 and clang14 compilers.
I have a quick & dirty macro which I used to quickly test my program:
#define ASSERT_EQUAL(expected, actualFunc, desc)
expected should be the first argument, and is a literal; actualFunc should be the second argument, and is a function call with parameters, an example call looks like:
ASSERT_EQUAL(true, test1(42), "cache-friendly");
In this macro, I will also timing the second argument(the function call), in order to make sure it works as expected, I need to make sure the parameters are passed in right order, or else it should error out., like below:
ASSERT_EQUAL(test1(42), true, "cache-friendly");
I tried:
static_assert(std::is_fundamental<decltype(expected)::value)
But it doesn't work as it won't error out even if I pass in the function call as first paramter expected, because its return value is a fundamental type.
is there a way to static assert and error out if the order of paramters are not as expected?
FYI - the macro implementation:
static int CaseNum = 0;
#define ASSERT_BASE(expected, actualFunc, desc) \
std::chrono::steady_clock clock; \
auto start = clock.now(); \
auto actual = actualFunc; \
auto elapsedTime = clock.now() - start; \
auto timeInUS = std::chrono::duration_cast<std::chrono::microseconds>(elapsedTime).count(); \
cout << boolalpha << "CASE " << ++CaseNum << ": " << "EXPECTED=" << expected << "; ACTUAL=" << actual << "; elapsedTime=" << timeInUS << "us" << " --- " << desc << endl; \
#define ASSERT_EQUAL(expected, actualFunc, desc) \
{ \
ASSERT_BASE(expected, actualFunc, desc) \
assert(expected == actual); \
}
#define ASSERT_NEAR(expected, actualFunc, desc) \
{ \
ASSERT_BASE(expected, actualFunc, desc) \
assert(fabs(expected - actual) < 0.0001); \
}
This is not really possible by inspecting the expression within the language, since C++ is continually expanding the horizons of what is allowed in a constant-expression. You could check that expected can be used as a constant expression by e.g. using it to initialize a constinit variable, but this could result in a false negative if the test function is constexpr, which it might well be.
Instead, you could perform textual introspection using the preprocessor "stringification" operator:
static_assert(std::string_view{#expected}.find('(') == std::string_view::npos, "expected must be a literal");
Example.
I might suggest another approach (without MACRO) to enforce that second argument is a function/callable (instead of result of function):
template <typename T, typename F>
void AssertRun(T expected, F f, const std::string& descr)
{
static int CaseNum = 0;
std::chrono::steady_clock clock;
const auto start = clock.now();
auto actual = f();
const auto elapsedTime = clock.now() - start;
const auto timeInUS =
std::chrono::duration_cast<std::chrono::microseconds>(elapsedTime).count();
std::cout << boolalpha << "CASE " << ++CaseNum << ": "
<< "EXPECTED=" << expected
<< "; ACTUAL=" << actual
<< "; elapsedTime=" << timeInUS << "us"
<< " --- " << desc << std::endl;
return actual;
}
template <typename T, typename F>
void AssertEqual(T expected, F f, const std::string& descr)
{
auto actual = AssertRun(expected, f, descr);
assert(expected == actual);
}
and then
AssertEqual(true, []{ return test1(42); }, "cache-friendly");
AssertEqual(test1(42), []{ return true; }, "cache-friendly"); would still be possible, but seems less probable to confound.
Some time ago, I made this beautiful assert macro for c and c++ programs
#define ASSERT(truthy, message) \
if (!(truthy)) \
{\
cout << message << " on line " << __LINE__ << " in file " << __FILE__ << ". Check was " << #truthy << endl;\
}
Scatter ASSERT calls throughout your code, and it will warn you whenever the truthy value is not truthy! Very handy during development to remind you of potential mistakes.
ex
ASSERT(filesFound > 0, "Couldn't find any files, check your path!");
When filesFound is 0, the macro will print out
Couldn't find any files, check your path! on line 27 in file
openFiles.c. Check was filesFound > 0
Now what I want it to print, to give me even more relevant information, is the value of any variables passed into the truthy parameter. Like this
Couldn't find any files, check your path! on line 27 in file
openFiles.c. Check was filesFound > 0, filesFound is 0
This seems lisp-like territory, I wonder, is there any black magic c preprocessing that I can use to evaluate variables and functions to their values, without evaluating the truthy statement?
I assume to be disappointed.
An alternative solution which I've always used is to support varargs in the macro and then force the assert user to specify the relevant message / variables - it's a little bit of extra work each time, but on the plus side you can get exactly the formatting that you want and include information not available in the "truthy" bit, e.g:
#define ASSERT(truthy, message, ...) \
if (!(truthy)) \
{\
MyAssertHandler(__LINE__, __FILE__, #truthy, message, ##__VA_ARGS__);
}
Then you're handler is just a fairly standard var-arg function that can use e.g. vsnprintf to generate the message and output it, e.g. off the top of my head:
void MyAssertHandler(int line, const char* file, const char* expressionStr, const char* format, ...)
{
// Note: You probably want to use vsnprintf instead to first generate
// the message and then add extra info (line, filename, etc.) to
// the actual output
va_list args;
va_start(args, format);
vprintf(format, args);
va_end(args);
// Log to bug database, DebugBreak() if a debugger is attached, etc.
}
usage:
ASSERT(IsBlah(), "BlahBlah: x = %.2f, name = %s", GetX(), GetName());
I cannot imagine a way to do it... except by passing another parameter
#define ASSERT_PARAM(truthy, message, param) \
if (!(truthy)) \
{\
cout << message << " on line " << __LINE__ << " in file " << __FILE__ << ". Check was " << #truthy << ", value was " << param << endl;\
}
You would use it that way:
ASSERT_PARAM(filesFound > 0, "Couldn't find any files, check your path!", filesFound);
getting:
Couldn't find any files, check your path! on line 27 in file openFiles.c. Check was filesFound > 0, value was 0
What you are trying to do sounds very complicated. I'm afraid in C++ it's not possible.
Technically what you are evaluating is a bool expression so you can pass it to a parser whenever the assertion fails. The parser then will build the expression tree, get the leaves (elements of the expression) and return them. The returned values then should be printed out. To do that you will need support for reflection which is actually not supported in C++ AFAIK.
Maybe not the dream solution, but you can pass whole statements to a macro.
#define ASSERT(trusty, action) if (!trusty) { action }
ASSERT(trusty, cout << a << b;)
ASSERT(trusty, printf("%d, %f\n", a, b);)
I think you can split up the truthy Expression like they do it in the first answer here and then you can probably print the individual values. But I'm not sure if it actually works.
The printing could then be resulved using a variadic template function
Perhaps you could compromise and only allow 2 variables and 1 operator in the assertion expression? If so, you could make an ad hoc solution like this:
#include <iostream>
#include <string>
#define STRINGIFY(x) #x
#define BIN_ASSERT(obj1, op, obj2, msg) \
if(!(obj1 op obj2)) \
{ \
std::cout << msg << " on line " << __LINE__ \
<< " in file " << __FILE__ \
<< "." << std::endl \
<< "Check was " \
<< STRINGIFY(obj1) STRINGIFY(op) STRINGIFY(obj2) \
<< "." << std::endl \
<< "Operator " << #obj1 << ": " << obj1 \
<< "." << std::endl \
<< "Operator " << #obj2 << ": " << obj2 \
<< "." << std::endl; \
}
int main (void)
{
int x = 2;
int y = 3;
std::string s1 = "hello";
std::string s2 = "world";
BIN_ASSERT(1, +, -1, "Value zero"); std::cout << std::endl;
BIN_ASSERT(x, ==, y, "Numbers not equal"); std::cout << std::endl;
BIN_ASSERT(s1, ==, s2, "Strings not equal"); std::cout << std::endl;
}
Output:
Value zero on line 30 in file test.c.
Check was 1+-1.
Operator 1: 1.
Operator -1: -1.
Numbers not equal on line 31 in file test.c.
Check was x==y.
Operator x: 2.
Operator y: 3.
Strings not equal on line 32 in file test.c.
Check was s1==s2.
Operator s1: hello.
Operator s2: world.
I wonder if having the macro take a message is really that useful. A failed assertion is a message to the developer that there is a bug in the code that caused an exceptional behaviour or put the program in an unacceptable state. The user has less to do with it (if they even have access to the source code).
The code below defines an ASSERT macro that takes a boolean expression, evaluates it and prints an informational message. The message contains a value that you've asked to inspect upon failing the assertion.
The macro, just like the standard assert() macro (in <cassert>) goes on to call abort() (from <cstdlib>) to cause an abnormal program termination. This is what you want, because the program entered a state in which it didn't know what more to do.
I'm using std::printf() here for brevity. You do whatever you want.
#include <cstdlib>
#include <cstdio>
#define ASSERT(value, inspect) \
if (!(value)) { \
std::printf("ASSERTION FAILED: '%s', %s is %d: %s#%s:%d\n", #value, \
#inspect, inspect, __func__, __FILE__, __LINE__); \
abort(); \
}
int foo() { return 42; }
int main()
{
// ...
ASSERT(foo() - 40 == 1, foo());
//...
}
Program run:
$ ./a.out
ASSERTION FAILED: 'foo() - 40 == 1', foo() is 42: main#prog.cc:16
Abort
It's not possible to do exactly what you ask for without adding more parameters to the macro. At some point you'll have to stop and realize that you're spending time on creating a text string that you do not want to see.
You need to build an expression 'grabber' / builder.
The macro would become something like:
#define ASSERT_PARAM(truthy, message, param) \
if (!(truthy)) \
{\
Grabber g;
g << #truthy; // grab expression as string
g % truthy; // grab expression and values
cout << message << " on line " << __LINE__ << " in file " << __FILE__ << ". Check was " << #truthy << ", value was " << param << endl;\
cout << g; \
}
What does Grabber do?
It is a bunch of crazy C++ that builds up an expression. It would overload every operator to 'grab' the params of the operator. Every operator returns a reference to the grabber, so it can grab the next operator. ie
Grabber g;
g % filesFound > 0;
Since % (and * and /) have high precedence, the above parses like:
((g % filesFound) > 0)
If template<typename T> Grabber::operator%(T const & val) just records (or prints) the value passed in (ie filesFound), and - importantly - returns itself (g) so that it becomes part of the next expression: ie it becomes g > 0. Causing template<typename T> Grabber::operator>(T const & val) to be called, and > 0 to be recorded.
Then cout << g can spew out everything grabbed.
As mentioned above "It is possible — the Catch library does it. But it’s hellishly difficult".
P.S. you should wrap your macro in a do ... while 0 like this:
#define ASSERT_PARAM(truthy, message, param) \
do \
{ \
if (!(truthy)) \
{\
cout << message << " on line " << __LINE__ << " in file " << __FILE__ << ". Check was " << #truthy << ", value was " << param << endl;\
cout << g; \
} \
} while (0)
What you have currently means that this is valid code:
ASSERT(foo != 0)
else
{
}
And this is NOT valid code:
if (foo != nullptr)
ASSERT(foo->bar != nullptr);
else
x = 10;
Surprisingly, I solved a similar problem before, but I'm not sure if it could help you in this case.
The original solution was proposed by Andrei Alexandrescu in the article Enhancing Assertions, and with no question, relying on some macro tricks.
This amazing facility can be used as the following:
string s1, s2;
...
SMART_ASSERT(s1.empty() && s2.empty())(s1)(s2);
And if something goes wrong, the message would be displayed
Assertion failed in matrix.cpp: 879412:
Expression: 's1.empty() && s2.empty()'
Values: s1 = "Wake up, Neo"
s2 = "It's time to reload."
Be noted that, the SMART_ASSERT can capture infinite variables, theoretically.
For implementation details, please check out the article.
I am wondering if how I can write a function to detect the parameter type, value and function name and return value of another function.
For example. I have a function:
double average(string datapath, double *data, int numofinput)
{
// some code here
}
I want to have another function, such as detector(), which can be inserted into the function to be detected, like
double average(string datapath, double *data, int numofinput)
{
// some code here
detector();
}
and the detector will return:
name: average
returned value: 2.43
pathname: string='C:/Users/Nick/Data/'
data: pointer=0x0065
numofinput: int=17
Somthing like that. Any suggestion is highly appreciated. Thanks.
Nick
In general this can't be done:
detector would need to show the return value before you actually return anything, which is same as mind reading
when a binary is built, the names of the functions are not available inside it (in general, except for exports)
your average function might not be a function at all, as compiler could inline it.
For specific cases, however, you could be able to get this information - under assumption that you have debug symbols available, which in general you don't.
Here's an (untested) idea:
#define DETECTOR(name, ...) detector_wrapper(name, #name, ##__VA_ARGS__)
template <typename R, typename ...Args, typename ...Brgs>
R detector_wrapper(R(&f)(Args...), char const * name, Brgs &&... brgs)
{
auto && result = f(std::forward<Brgs>(brgs)...);
std::cout << "Function name: " << name << std::endl
<< "Return type: " << demangle(R) << std::endl
<< "Return value: " << result << std::endl;
return result;
}
Usage:
double d = DETECTOR(average, path, data, n);
With a bit more work you can also print the types of the arguments and their values, though not their names (obviously, since the names are not part of the declaration, only of the definition).
Ok, here's another way to do it, including printing parameter names and types. It is not very elegant for two reasons:
It requires a new macro for every number of parameters you send, and ...
It's freaking macros! I've never seen them used elegantly (and this is no exception).
So here goes:
#include <iostream>
#define DETECTOR_0ARG_FUNC(RETTYPE, NAME) \
RETTYPE NAME() \
{ \
std::cout << "Function Name: " #NAME << std::endl; \
std::cout << "Returns: " #RETTYPE << std::endl; \
std::cout << "No Parameters" << std::endl;
#define DETECTOR_1ARG_FUNC(RETTYPE, NAME, PARAM1TYPE, PARAM1NAME) \
RETTYPE NAME(PARAM1TYPE PARAM1NAME) \
{ \
std::cout << "Function Name: " #NAME << std::endl; \
std::cout << "Returns: " #RETTYPE << std::endl; \
std::cout << "Pameter 1 (" #PARAM1TYPE " " #PARAM1NAME "): " << PARAM1NAME << std::endl;
#define DETECTOR_RETURN(RETTYPE, VALUE) \
RETTYPE __retval = (VALUE); \
std::cout << "Returning: " << __retval << std::endl << std::endl; \
return __retval;
#define DETECTOR_END_FUNC \
}
DETECTOR_0ARG_FUNC(int, GetFiveFactorial)
int result = 1;
for(int i=5; i>0; i--)
{
result = result * i;
}
DETECTOR_RETURN(int, result)
DETECTOR_END_FUNC
DETECTOR_1ARG_FUNC(int, GetFactorial, int, initVal)
int result = 1;
for(int i=initVal; i > 0; i--)
{
result = result * i;
}
DETECTOR_RETURN(int, result);
DETECTOR_END_FUNC
int main(int argc, char **argv)
{
GetFiveFactorial();
GetFactorial(7);
return 0;
}
The output:
Function Name: GetFiveFactorial
Returns: int
No Parameters
Returning: 120
Function Name: GetFactorial
Returns: int
Pameter 1 (int initVal): 7
Returning: 5040
I kindof don't recommend that you do this. But from a theoretical standpoint, it is possible this way.
I'm writing a logging class at the moment. The Logger works with streams and also prints the object which is logging at the moment. Here is the macro:
#define OBJLOG(DL, what) DL <= this->Logger->getDebugLevel() ? *this->Logger << DL << "[" << this->Name << "]: "<< what << std::endl : this->Logger->doNothing();
The pseudo code Variant for better overview:
#define OBJLOG(debuglevel, what) debuglevel <= logger.debuglevel ? logger.log(what) : logger.doNothing()
Is there any way to get around the doNothing function call, like doing nothing at all?
#define OBJLOG(DL, what) do { if(DL <= this->Logger->getDebugLevel()) *this->Logger << DL << "[" << this->Name << "]: "<< what << std::endl; } while(0)
See Why use apparently meaningless do-while and if-else statements in macros? for an explanation. (The do {} while(0) isn't strictly necessary here, but I would prefer not to leak an ostream.)
Also, you should always wrap macro argument uses in parentheses, like:
#define OBJLOG(DL, what) do { if((DL) <= this->Logger->getDebugLevel()) *this->Logger << (DL) << "[" << this->Name << "]: "<< (what) << std::endl; } while(0)
Finally, you should move this code into a function and call that in your macro (if you really insist on using a macro) to avoid evaluating your macro arguments more than once.
Have your logger.log() function return a boolean.
Connect your predicates with an and like this: debuglevel <= logger.debuglevel && logger.log
That should do the trick.
If you want an expression that does nothing, try (void)0.