Please note C++03! any C++11 solutions are not good for me, but do post them just for knowledge sake.
I know the preprocessor can do things like:
#define FOO 4
#if FOO == 4
cout<<"hi"<<endl;
#endif
What I need is:
#define BAR(X)\
#if X == 4\
cout<<"hi"<<endl;\
#endif
main.cpp
BAR(4)
I don't see why all the needed information wouldn't be available in preprocessor time.
So, Please tell me how to achieve this kind of behavior.
edit 1:
A normal if condition won't work for my case, because I also do things like:
#define BAR(X)\
#if X == 4\
int poop;
#elif
double poop;
#endif
As you've discovered, you can't do this in the way that you've attempted. Macro expansion simply doesn't have inline conditional evaluation, so you'd have to create multiple macros instead.
However, if you're just trying to "optimise" normal code flow, you can rely on your compiler's optimizations. Consider this:
if (true) {
std::cout << "Hi\n";
}
The resulting program will not have any conditional checks in it, because true is always truthy.
Similarly:
if (false) {
std::cout << "Hi\n";
}
The resulting program will not contain any code to produce output, because false is never truthy.
Similarly:
if (4 != 4) {
std::cout << "Hi\n";
}
The program will still not contain the std::cout code.
In many cases, you may use this fact to keep your code simple and achieve your desired effect:
#define BAR(X) \
if ((X) == 4) {
std::cout << "hi" << std::endl;\
}
The constraint here, of course, is that an if statement must be valid at the place you write BAR(5), or BAR(42) or BAR(999).
This is also flexible in that now you can use a runtime value (like BAR(i)) and, although the conditional can no longer be collapsed at compile-time, in such a case you'd have no reason to expect that anyway.
I take this approach in my logging macro: the macro, when called for LOG_LEVEL_DEBUG, expands to a conditional that is statically known never to match, in release builds.
The idea is to let the compiler do the optimising.
You're also going to want to consider using a little macro expansion trick to avoid problems with subsequent else clauses.
You can do this with the preprocessor if the domain of values for the conditional parameter is well-known (and preferably small). For example, supposing the parameter can only have the values 0 and 1:
#define DOIT_0(X)
#define DOIT_1(X) X
#define CONCAT_(X, Y) X ## Y
#define MAYBE(X) CONCAT_(DOIT_, X)
#define BAR(X) MAYBE(X)( cout<<"hi"<<endl; )
#define YESNO 0
BAR(YESNO)
Live on coliru.
Beware of unprotected commas in the argument to BAR.
For equality checks, again over a small range:
#define CONCAT3_(X,Y,Z) X ## Y ## Z
#define EQUAL_0_0(X) X
#define EQUAL_1_1(X) X
#define EQUAL_1_1(X) X
#define EQUAL_0_1(X)
#define EQUAL_0_2(X)
#define EQUAL_1_0(X)
#define EQUAL_1_2(X)
#define EQUAL_2_0(X)
#define EQUAL_2_1(X)
#define DO_IF_EQUAL(X, Y) CONCAT3_(EQUAL_, X, Y)
#define BAR(X) DO_IF_EQUAL(X, 2) ( std::cout << "hi\n"; )
If you can use Boost, you could do this with Boost.Preprocessor:
#define BAR(X) BOOST_PP_EXPR_IF(BOOST_PP_EQUAL(X, 4), cout << "hi" << endl;)
Some answers here were better than others.
The one I accepted was posted by Christian Kiewiet in a comment, but it was the most accurate for my purpose.
Here is the expanded version:
useCases.h
enum UseCases{
useCase1=0,
useCase2,
useCaseNumber//always last for iterations
}
specializer.h
#include "useCases.h"
<template UseCases theCase>
struct StaticCase{
//empty, thus accidents calling from this can't happen
}
//specialization
template<>
class StaticCase<UseCases::useCase1>{
typedef int T;
static foo(T arg){cout<<"case1";};
}
template<>
class StaticCase<UseCases::useCase2>{
typedef double T;
static foo(){cout<<"case2";};
}
Now, I can do
#define BAR1(useCase) StaticCase<useCase>::foo();
or
#define BAR2(useCase) StaticCase<useCase>::T var;
and the call:
BAR1(UseCases::useCase1)//output - case1
BAR1(UseCases::useCase2)//output - case2
Related
I want to create a macro that replaces all calls to printf, more specifically mbedtls_printf (which behaves the exact sameway as printf) with nothing.
I know I can use #define mbedtls_printf to replace mbedtls_printf with nothing, but this will still leave the parameters/parenthesis intact.
Edit - I forgot to mention that mbedtls_printf is a macro that replaces itself with sgx_printf
I would go with:
#define printf(...) (0)
The benefit here is that it will continue to compile in cases where someone actually bothers to check the return from printf (rare but not unheard of).
The following works, at least with gcc 8. A brief search suggests that variadic macros were introduced with C99:
#define printf(...) do { } while (0)
int main()
{
printf("Hello %s?\n", "world");
return 0;
}
You want to use the ol' "do {} while (0)" trick, in order to avoid surprises like:
if (something)
printf("Something else");
will_this_be_invoked_or_not();
You can't make printf() disappear completely. Because this would make the next line a logical part of the preceding if statement. Hillarity ensues. That's why you still have to leave something in place.
If you completely no-op out the printf statements, there may be a bug lurking. Consider the following code:
printf("Result is %d\n", DoSomethingVeryImportant());
When you replace the printf call with a macro, you likely still want to make sure the inner function call to DoSomethingVeryImportant() is invoked. Otherwise, you've changed the logic of your program.
And I suppose you might want to have your mbedtls_printf actually call printf for debug builds, but be a no-op in a retail build.
If all of the above is of value, consider this as mbedtls_printf.h:
#ifndef MBEDTLS_PRINTF_H
#define MBEDTLS_PRINTF_H
#include <stdarg.h>
#include <stdio.h>
#ifdef DEBUG_BUILD
inline int printf_stub(const char* s, ...)
{
va_list args;
va_start(args, s);
vprintf(s, args);
va_end(args);
}
#define mbedtls_printf(...) printf_stub(__VA_ARGS__)
#else
inline int printf_stub(...){return 1;}
#define mbedtls_printf(...) printf_stub(__VA_ARGS__)
#endif
#endif
Then in code:
#include <iostream>
#include "mbedtls_printf.h"
int ImportantFunction()
{
std::cout << "Really important code" << std::endl;
return 42;
}
int main()
{
mbedtls_printf("Result of a very important step: %d\n", ImportantFunction());
mbedtls_printf("This just happened");
mbedtls_printf("Result of a another important step: ", 43, 44, ImportantFunction());
return 0;
}
The compiler will optimize out the empty function call and still invoke ImportantFunction() as it was doing originally.
I know I can use #define mbedtls_printf to replace mbedtls_printf with nothing, but this will still leave the parameters/parenthesis intact.
It's OK if the argument list remains, because then it will be treated as an expression. If we have an expression and we do nothing to it, then it will just be optimized out (on any decent compiler). Consider the following:
int x(char a, double b)
{
return printf("%c %f\n", a, b);
}
#define x
int main(void)
{
x('P', 3.14);
}
The compiler sees the following code for main:
('P', 3.14);
This expression evaluates to 3.14 (the comma operator returns its right-hand operand). Such an expression is quietly optimized.
Just use a lambda: (Variadic macros since C99)
#define printf(...) []{}()
What this does is simply replace the printf() calls to []{}()... This just means an empty function call... which can be formatted to be like this:
#define printf(...) [] { \
}()
Or, even this suffices:
// Replacing printf() with an empty function that just takes variadic arguments
#define printf [](...){}
Edit: You can also use:
#define printf void(0)
Assume we have a #define FOO(x,y) something.
I want to construct such macro #define BAR that BAR(x)(y) would call FOO(x,y). How can I do it, if it's possible at all?
I tried following:
#define BAR(x) FOO(x, BAR_
#define BAR_(y) y)
But got:
error: unterminated argument list invoking macro "FOO"
Here's a MCVE:
#include <iostream>
#define FOO(x,y) std::cout << x << y << '\n';
#define BAR(x) FOO(x, BAR0
#define BAR0(y) y)
#define STR(...) STR0(__VA_ARGS__)
#define STR0(...) #__VA_ARGS__
int main()
{
std::cout << STR( BAR(1)(2) );
}
Another attempt:
#define BAR FOO BAR0
#define BAR0(x) (x, BAR1
#define BAR1(y) y)
This one compiles, but leaves FOO (1, 2) unexpanded in the end.
MCVE:
#include <iostream>
#define FOO(x,y) std::cout << x << y << '\n';
#define BAR FOO BAR0
#define BAR0(x) (x, BAR1
#define BAR1(y) y)
#define STR(...) STR0(__VA_ARGS__)
#define STR0(...) #__VA_ARGS__
int main()
{
// Prints `FOO (1, 2)`, but I want `std::cout << 1 << 2 << '\n';`
std::cout << STR( BAR(1)(2) );
}
1. Dissecting the error
Let's start here:
#define BAR(x) FOO(x, BAR_
#define BAR_(y) y)
#define FOO(x,y) foo{x|y}
BAR(1)(2)
Note that I'm only going to use the preprocessor to debug the preprocessor (why do I need to build C++ programs, which invokes the preprocessor anyway, when I can simply just invoke the preprocessor? (That's rhetorical o/c; I'm just telling a story here)).
Here's how the CPP looks at this. We see BAR; that's a function-like macro. Interesting, but not actionable unless we see an open parentheses. Next, we see... an open parentheses. Now we're getting somewhere... we need to identify its arguments. So we keep scanning: BAR(1)... there... that's the matching open parentheses... looks like we're invoking with one argument. BAR it turns out is defined with one argument, so this works great.
Now we perform argument substitution... so we note that BAR's replacement list mentions its parameter (x) in a non-stringifying, non-pasting way. That means we should evaluate the corresponding argument (1), which is easy... that's just itself. That evaluation result then replaces the parameter in the replacement list, so we have FOO(1, BAR_. We're now done with argument substitution.
The next thing we need to do is rescan and further replacement. So we rescan... FOO, ah, yes. That's a function-like macro... FOO( ...and it's being invoked. Now we're getting somewhere... we need to identify its arguments. So, we keep scanning: FOO(1, BAR_(2)...and, suddenly we reach the end of the file. Huh? That's not right. FOO is being invoked; it's supposed to have a matching parentheses.
You might naively think that BAR_(2) should be invoked, but that's not how macros work. They evaluate outer-in, and the "in" (aka, argument tokens) only evaluates if there's a mention of the parameter in the replacement list, where said mention is not a stringification or paste.
Note that if FOO were not a function-like macro, this story would go an entirely different direction. In such a case, FOO( would simply be tokens the preprocessor doesn't care about... so by the time it sees BAR_(2), it will be invoking a macro. But there's another "cheat"; if FOO is passed over without actually invoking the macro FOO, the tokens would also be skipped over. In both cases, FOO(1, 2) will eventually be produced, which is what you want. But if you then want to evaluate FOO as a function-like macro, you have only one choice. You need a second pass; first pass actually allows your second argument in the sequence to be invoked to build your macro, and this pass must not allow FOO to be invoked. The second pass is needed to invoke it.
2. How to do this
Well, that's easy enough:
#define DELAY()
#define BAR(x) FOO DELAY() (x, BAR_
#define BAR_(y) y)
#define FOO(x,y) foo{x|y}
#define EVAL(...) __VA_ARGS__
BAR(1)(2)
EVAL(BAR(1)(2))
Here's how this is different (first line). After BAR's argument substitution, its replacement list is now FOO DELAY() (1, BAR_ instead of just FOO(1, BAR_. Now, during the rescan, it still sees FOO, which is still interesting... but the next token it sees is DELAY, not an open parentheses. So the CPP in this pass decides it's not invoking FOO and passes on it. After the full DELAY() expansion, which produces nothing, it then just sees (1, BAR_; the first three are just tokens. BAR_, however, is a macro invocation, and so goes the story... so the result of expanding BAR(1)(2) is to produce the tokens FOO(1, 2), error free. But that doesn't evaluate FOO.
The EVAL, however, accepts BAR(1)(2) as an argument. Its replacement list mentions its "parameter" (varying arg variant), so BAR(1)(2) is fully evaluated, producing FOO(1, 2). Then FOO(1, 2) is rescanned, which is when FOO actually gets invoked.
I would like to ask why this code prints out 2 instead of 0. Doesn't #define "assign" values to the names of the macros and calculate also the result? How does it give this answer?
#include <iostream>
using namespace std;
#define A 0
#define B A+1
#define C 1-B
int main() {
cout << C<<endl;
return 0;
}
Macros are direct text replacements That means
#define C 1-B
becomes
1-A+1
and then A gets expanded so we have
1-0+1
which is 2. If you want 0 then stop using macros and instead use constant variables
const int A = 0;
const int B = A + 1;
const int C = 1 - B;
And now C is 0.
The preprocessor expands the C macro to 1-B, which expands to 1-A+1 which expands to 1-0+1 which equals 2. Don't think of it in terms of sequential assignment, but you can get the desired behavior by adding parenthesis around the macro definitions. Then the C macro would expand to (1-B), then (1-(A+1)) then (1-((0)+1)) which equals 0.
Edit:
As an example, the code snip below prints 42, even though BAR is "assigned" to FOO when FOO equals 17. This is because the expansion is deferred until it's actually used. On the cout line, BAR is still equal to FOO, but at that point, FOO is now 42, not 17. Note that it's bad practice to redefine a macro without first #undefining it.
#define FOO 17
#define BAR FOO
#define FOO 42
cout << BAR << endl;
Because C expands to 1-0+1
Preprocessor defines simply replace text and don't care about operator precedence or calculation rules.
I previously asked about function overloading based on whether the arguments are constexpr. I'm trying to work around the disappointing answer to that question to make a smarter assert function. This is roughly what I am trying to do:
inline void smart_assert (bool condition) {
if (is_constexpr (condition))
static_assert (condition, "Error!!!");
else
assert (condition);
}
Basically, the idea is that a compile-time check is always better than a run-time check if it's possible to check at compile time. However, due to things like inlining and constant folding, I can't always know whether a compile time check is possible. This means that there may be cases where assert (condition) compiles down to assert(false) and the code is just waiting for me to run it and execute that path before the I find out there is an error.
Therefore, if there were some way to check whether the condition is a constexpr (due to inlining or other optimizations), I could call static_assert when possible, and fall back on a run-time assert otherwise. Fortunately, gcc has the intrinsic __builtin_constant_p (exp), which returns true if exp is a constexpr. I don't know if other compilers have this intrinsic, but I was hoping that this would solve my problem. This is the code that I came up with:
#include <cassert>
#undef IS_CONSTEXPR
#if defined __GNUC__
#define IS_CONSTEXPR(exp) __builtin_constant_p (exp)
#else
#define IS_CONSTEXPR(exp) false
#endif
// TODO: Add other compilers
inline void smart_assert (bool const condition) {
static_assert (!IS_CONSTEXPR(condition) or condition, "Error!!!");
if (!IS_CONSTEXPR(condition))
assert (condition);
}
#undef IS_CONSTEXPR
The static_assert relies on the short circuit behavior of or. If IS_CONSTEXPR is true, then static_assert can be used, and the condition is !true or condition, which is the same as just condition. If IS_CONSTEXPR is false, then static_assert cannot be used, and the condition is !false or condition, which is just the same as true and the static_assert is ignored. If the static_assert cannot be checked because condition is not a constexpr, then I add a run-time assert to my code as a last-ditch effort. However, this does not work, thanks to not being able to use function arguments in a static_assert, even if the arguments are constexpr.
In particular, this is what happens if I try to compile with gcc:
// main.cpp
int main () {
smart_assert (false);
return 0;
}
g++ main.cpp -std=c++0x -O0
Everything is fine, compiles normally. There is no inlining with no optimization, so IS_CONSTEXPR is false and the static_assert is ignored, so I just get a run-time assert statement (that fails). However,
[david#david-desktop test]$ g++ main.cpp -std=c++0x -O1
In file included from main.cpp:1:0:
smart_assert.hpp: In function ‘void smart_assert(bool)’:
smart_assert.hpp:12:3: error: non-constant condition for static assertion
smart_assert.hpp:12:3: error: ‘condition’ is not a constant expression
As soon as I turn on any optimizations and thus potentially allow static_assert to be triggered, it fails because I cannot use function arguments in the static_assert. Is there some way to work around this (even if it means implementing my own static_assert)? I feel my C++ projects could theoretically benefit quite a bit from a smarter assert statement that catches errors as early as possible.
It doesn't seem like making smart_assert a function-like macro will solve the problem in the general case. It will obviously make it work in this simple example, but condition may have come from a function two levels up the call graph (but still becomes known to the compiler as a constexpr due to inlining), which runs into the same problem of using a function parameter in a static_assert.
This should help you start
template<typename T>
constexpr typename remove_reference<T>::type makeprval(T && t) {
return t;
}
#define isprvalconstexpr(e) noexcept(makeprval(e))
Explicit is good, implicit is bad, in general.
The programmer can always try a static_assert.
If the condition can not be evaluated at compile time, then that fails, and the programmer needs to change to assert.
You can make it easier to do that by providing a common form so that the change reduces to e.g. STATIC_ASSERT( x+x == 4 ) → DYNAMIC_ASSERT( x+x == 4 ), just a renaming.
That said, since in your case you only want an optimization of the programmer’s time if that optimization is available, i.e. since you presumably don’t care about getting the same results always with all compilers, you could always try something like …
#include <iostream>
using namespace std;
void foo( void const* ) { cout << "compile time constant" << endl; }
void foo( ... ) { cout << "hm, run time,,," << endl; }
#define CHECK( e ) cout << #e << " is "; foo( long((e)-(e)) )
int main()
{
int x = 2134;
int const y = 2134;
CHECK( x );
CHECK( y );
}
If you do, then please let us know how it panned out.
Note: the above code does produce different results with MSVC 10.0 and g++ 4.6.
Update: I wondered how the comment about how the code above works, got so many upvotes. I thought maybe he's saying something I simply don't understand. So I set down to do the OP's work, checking how the idea fared.
At this point I think that if the constexpr function thing can be be made to work with g++, then it's possible to solve the problem also for g++, otherwise, only for other compilers.
The above is as far as I got with g++ support. This works nicely (solves the OP's problem) for Visual C++, using the idea I presented. But not with g++:
#include <assert.h>
#include <iostream>
using namespace std;
#ifdef __GNUC__
namespace detail {
typedef double (&Yes)[1];
typedef double (&No)[2];
template< unsigned n >
Yes foo( char const (&)[n] );
No foo( ... );
} // namespace detail
#define CASSERT( e ) \
do { \
char a[1 + ((e)-(e))]; \
enum { isConstExpr = sizeof( detail::foo( a ) ) == sizeof( detail::Yes ) }; \
cout << "isConstExpr = " << boolalpha << !!isConstExpr << endl; \
(void)(isConstExpr? 1/!!(e) : (assert( e ), 0)); \
} while( false )
#else
namespace detail {
struct IsConstExpr
{
typedef double (&YesType)[1];
typedef double (&NoType)[2];
static YesType check( void const* );
static NoType check( ... );
};
} // namespace detail
#define CASSERT( e ) \
do { \
enum { isConstExpr = \
(sizeof( detail::IsConstExpr::check( e - e ) ) == \
sizeof( detail::IsConstExpr::YesType )) }; \
(void)(isConstExpr? 1/!!(e) : (assert( e ), 0)); \
} while( false )
#endif
int main()
{
#if defined( STATIC_TRUE )
enum { x = true };
CASSERT( x );
cout << "This should be displayed, OK." << endl;
#elif defined( STATIC_FALSE )
enum { x = false };
CASSERT( x );
cerr << "!This should not even have compiled." << endl;
#elif defined( DYNAMIC_TRUE )
bool x = true;
CASSERT( x );
cout << "This should be displayed, OK." << endl;
#elif defined( DYNAMIC_FALSE )
bool x = false;
CASSERT( x );
cout << "!Should already have asserted." << endl;
#else
#error "Hey, u must define a test case symbol."
#endif
}
Example of the problem with g++:
[D:\dev\test]
> g++ foo.cpp -Werror=div-by-zero -D DYNAMIC_FALSE
[D:\dev\test]
> a
isConstExpr = true
!Should already have asserted.
[D:\dev\test]
> _
That is, g++ reports (even via its intrinsic function, and even wrt. creating VLA or not) that a non- const` variable that it knows the value of, is constant, but then it fails to apply that knowledge for integer division, so that it then fails to produce warning.
Argh.
Update 2: Well I'm dumb: of course the macro can just add an ordinary assert to have there in any case. Since the OP is only interested in getting the static assert when it's available, which isn't for g++ in some corner cases. Problem solved, and was solved originally.
How is the answer to the other question disappointing? It implements almost exactly what you presently describe, except for the way the compiler prints the text in the diagnostic message.
The reason it needs to be done with throw is that compile-time evaluation of constexpr in a context that could be evaluated at runtime is optional. For example, the implementation could choose to let you step through the constexpr code in debugging mode.
constexpr is a weak attribute of functions (declaration specifier) that cannot change the resulting value of an expression using the function. It is a guarantee that the semantic meaning at runtime is fixed at compile time, but doesn't allow you to specify a special compile-time shortcut.
As for flagging invalid conditions, throw is a subexpression which is invalid as a constant expression, except when hidden in the unevaluated side of ?:, &&, or ||. The language guarantees that this will be flagged at compile time, even if the debugger lets you step through it at runtime, and only if the flag is really triggered.
The language gets things right here. Unfortunately that cannot be reconciled with the special diagnostic message feature of static_assert or branching on constexpr-ness.
Here is some C++ code I'm playing around with:
#include <iostream>
#include <vector>
#define IN ,
#define FOREACH(x,y) for(unsigned int i=0;i<y.size();i++) { x=y[i];
#define ENDFOREACH }
using namespace std;
int main()
{
vector<int> ints;
ints.push_back(3);
ints.push_back(4);
ints.push_back(5);
ints.push_back(6);
FOREACH(int item IN ints)
cout << item;
ENDFOREACH
return 0;
}
However, I get an error:
macro "FOREACH" requires 2 arguments, but only 1 given
The code compiles if I change the IN to a comma. How can I get the IN to take the place of a comma?
Update: for those interested, here is the final version, which, if I do say so myself, is quite nice.
#include <iostream>
#include <vector>
#define in ,
#define as ,
#define FOREACH_(x,y,z) \
y x; \
if(z.size()) x = z[0]; \
for(unsigned int i=0,item;i<z.size();i++,x=z[i])
#define foreach(x) FOREACH_(x)
using namespace std;
int main()
{
vector<int> ints;
ints.push_back(3);
ints.push_back(4);
ints.push_back(5);
ints.push_back(6);
foreach(item as int in ints)
{
cout << item << endl;
}
return 0;
}
Others have already explained why it doesn't compile as is.
In order to make it work you have to give that IN a chance to turn into a comma. For that you can introduce an extra level of "indirection" in your macro definition
#define IN ,
#define FOREACH_(x,y) for(unsigned int i=0;i<y.size();i++) { x=y[i];
#define FOREACH(x) FOREACH_(x)
#define ENDFOREACH }
In this case you'll have to use some substitute for comma (like your IN) and can no longer specify comma explicitly. I.e. now this
FOREACH(int item IN ints)
cout << item;
ENDFOREACH
compiles fine, while
FOREACH(int item, ints)
cout << item;
ENDFOREACH
does not.
The compiler doesn't expand the IN macro before it reads the arguments to FOREACH. In fact, I think this is intentional (so that you can pass a comma to a macro).
Unfortunately, you'll have to use FOREACH(int item, ints).
You could also #define IN (make it nothing) and then use FOREACH(int item, IN ints), which is not quite as nice, but is acceptable.
That said, you may just want to use STL or Boost for foreach, unless you specifically want to create your own.
Expansion for IN doesn't happen early enough in your example, but you can pass the expanded version to another macro:
#define FOREACH(x) DO_FOREACH(x)
#define DO_FOREACH(x,y) for( ... ) ...
#define IN ,
#define XFOREACH(x,y) for(unsigned int i=0;i<y.size();i++) { x=y[i];
#define FOREACH(x) XFOREACH(x)
#define ENDFOREACH }
As previous posters have noted, the preprocessor does not expand macros in the arglist before it splits it into argument. However, as long as the macro doesn't use # or ##, it expands macros in the args before substituting them into the macro body, so an extra indirection does the trick
Check out BOOST_FOREACH - it does what you want
http://www.boost.org/doc/libs/1_35_0/doc/html/foreach.html
The preprocessor doesn't expand the IN to a comma until after it reads the arguments to FOREACH.
I'm pretty sure that the c++ preprocessor is one pass only, so you'll have to use:
FOREACH(int item, ints)
cout << item;
ENDFOREACH