Overriding for preprocessor loops

I want to do something evil. I want to override for loops to change the conditional. Is there any way to do this?

The GCC documentation supports keyword overrides: http://gcc.gnu.org/onlinedocs/cpp/Macros.html

What I'm trying to do is make a โ€œprobabilisticโ€ wrapper for C ++ to see if I can do anything interesting with it.

#include <iostream> #include <cstdlib> #define P 0.85 #define RANDOM_FLOAT ((float)rand()/(float)RAND_MAX) #define RANDOM_CHANCE (RANDOM_FLOAT < P) #define if(a) if((a) && RANDOM_CHANCE) #define while(a) while((a) && RANDOM_CHANCE) // No more for loops or do-while loops #define do #define goto // Doesn't work :( //#define for(a) for(a) if(!RANDOM_CHANCE) { break; } int main() { srand(time(NULL)); //Should output a random list of Y and N's for(int i=0; i < 100; ++i) { if(i < 100) { std::cout << "Y"; } else { std::cout << "N"; } } std::cout << std::endl; // Will loop for a while then terminate int j = 0; while(j < 100) { ++j; std::cout << j << "\n"; } std::cout << std::endl; return 0; } 

Perhaps a more legitimate use would be to count the number of loop iterations in a running program, for example, by matching

 for(int i=0; i < 10; ++i) 

to

 for(int i=0; i < 10; ++i, ++global_counter) 

Is it possible to accomplish what I'm trying to do?


EDIT: Thanks for the answers - I really appreciate that!

One of the things I can do with this is to simulate a fair coin (effectively making P equal to 0.5), noting that if you have a biased coin, Pr (HT) == Pr (TH). I did not find this trick, but it is useful. This means that you can approximate any probability distribution for P.

 bool coin() { bool c1 = false; bool c2 = false; if(true) { c1 = true; } if(true) { c2 = true; } //If they have different faces. bool valid = (c1 && !c2) || (!c1 && c2); bool result = c1; if(valid) { return result; } return coin(); } 
+4
source share
3 answers

Have you tried adding else to the for loop? This should make it work.

 #define for(a) for(a) if(!RANDOM_CHANCE) { break; } else for (int i = 0; i < 10; ++i) { // do something } /* should roughly compile to: for (int i = 0; i < 10; ++i) if(!RANDOM_CHANCE) { break; } else { // do something } or (differing only in whitespace): for (int i = 0; i < 10; ++i) if(!RANDOM_CHANCE) { break; } else { // do something } */ 
+8
source

You have shown it already. Here is a compiled example:

 #include <iostream> unsigned globalCounter = 0; #define for(x) for(x, ++globalCounter) int main () { for (int i=0; i<10; ++i); for (int i=0; i<10; ++i); std::cout << globalCounter << '\n'; } 

These outputs 20. However, existing code, such as

 for (int i=0; i<x; ++i, foobar+=20) 

will be broken because it now passes two arguments to the macro.

You will need an overload macro or variable macros. The latter is supported on C99, and C ++ 11 outputs it, so if you want evil to happen:

 unsigned globalCounter = 0; #define for(...) for(__VA_ARGS__, ++globalCounter) #include <iostream> void main () { int another = 0; for (int i=0; i<10; ++i, ++another); for (int i=0; i<10; ++i, ++another); std::cout << globalCounter << ' ' << another << '\n'; } 

then

 g++ --std=c++0x source.cc ./a.out 20 20 

I do not support this. Macros can harm your children.

+4
source

This does not work because the block no longer refers to the for statement. Conversion becomes

 for (int i=0; i < 100; ++i) { if (!RANDOM_CHANCE) { break; } } // unrelated to the 'for' above. { if(i < 100) { std::cout << "Y"; } else { std::cout << "N"; } } 

Instead, you can simply write

 #define for(...) for(__VA_ARGS__) if(RANDOM_CHANCE) 

So the code becomes

 for (int i=0; i < 100; ++i) if (RANDOM_CHANCE) { if(i < 100) { std::cout << "Y"; } else { std::cout << "N"; } } 

(Note that I used variable macros .)


And for the global_counter object, if you can guarantee that the increament part will never be empty, then it's easy:

 #define for(...) for(__VA_ARGS__, ++ global_counter) 

Otherwise (for example, the code has for(;;) ), I do not think that this is possible.

+1
source

Source: https://habr.com/ru/post/1400053/


All Articles