We have been restricted us to not use a loop in a program as a programming challenge.
Restrictions: You can not use while, for, goto and recursion.
The restrictions are pretty daunting. I couldn't really think of any proper solution. So I opted for this one which is achieved by modifying the return address.
Could this be any better?
#include <unistd.h>
#include <sys/mman.h>
#include <iostream>
#include <cstring>
void the__(){}
void magic__(){}
void loop__(){}
void function__(){}
void here__(){}
template <typename T>
struct for_
{
bool started = false;
void* fix = nullptr;
void(*body)(T&) = nullptr;
for_(void(*body)(T&))
: body(body)
{
auto do_for__ = uintptr_t(do_for_);
uint64_t magic[] = {5243466812662057800, 6135086863767628931ull, 10416984888688609608ull, 144};
mprotect((void*)(do_for__-do_for__%4096), 4096, 7);
std::memcpy((void*)(do_for__+135), magic, 25);
}
static void do_for_(T& ctx)
{
void** p = (void**)((char*)&p+16);
if (!ctx.started)
{
if (!ctx) return;
ctx.started = true;
ctx.fix = *p;
*p = (void*)do_for_;
}
ctx.body(ctx);
ctx.next();
if (ctx)
{
the__();
magic__();
loop__();
function__();
here__();
}
else
{
*p = ctx.fix;
}
}
};
struct For0ToN : for_<For0ToN>
{
For0ToN(int N, void(*f)(For0ToN&))
: for_<For0ToN>(f)
, N(N)
{
do_for_(*this);
}
operator bool() {return i < N;}
operator int() {return i;}
void next() {i++;}
int count() {return i;}
int i = 0, N = 0;
};
int main()
{
For0ToN(10, +[](For0ToN& i)
{
std::cout << int(i) << ": ";
For0ToN(i.count(), +[](For0ToN& i)
{
std::cout << int(i) << ". ";
});
std::cout << "\n";
});
std::cout << "done\n";
return 0;
}
The code is demonstrated here: https://coliru.stacked-crooked.com/a/3dd77ade501ac748
You could use longjmp
. Here's an example from cppreference:
#include <csetjmp>
#include <iostream>
std::jmp_buf jump_buffer;
[[noreturn]] void a(int count)
{
std::cout << "a(" << count << ") called\n";
std::longjmp(jump_buffer, count+1); // setjmp() will return count+1
}
int main() {
// loop from 0-9
volatile int count = 0; // local variables must be volatile for setjmp
if (setjmp(jump_buffer) != 10) {
a(count++); // This will cause setjmp() to exit
}
}
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