I am looking to do something somewhat evil. I want to redefine for loops to modify the conditional. Is there any way to do this?
From the GCC documentation, redefining keywords is supported: 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 make 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's 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;
}
A perhaps more legitimate use would be to count the number of loop iterations in a running program, for example by mapping
for(int i=0; i < 10; ++i)
to
for(int i=0; i < 10; ++i, ++global_counter)
Is it possible to accomplish what I am trying to do?
EDIT: Thanks for the responses - I really appreciate it!
One of the things I can do with this is simulate a fair coin (effectively force P to be 0.5), by noting that if you have a biased coin, Pr(HT) == Pr(TH). I didn't discover this trick, but it's useful. So that 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();
}
Have you tried adding an else
to your for
loop? That 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
}
*/
You showed it already. Here's a compilable 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';
}
This outputs 20. However, existing code like
for (int i=0; i<x; ++i, foobar+=20)
will break as it now passes two arguments to the for-macro.
What you would need is a macro overloads or variadic macros. The latter is supported in C99 and C++11 derives it, so if you want the 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 may harm your children.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With