I would like to know if it is possible to have sort of compile time loops.
For example, I have the following templated class:
template<class C, int T=10, int B=10> class CountSketch { public: CountSketch() { hashfuncs[0] = &CountSketch<C>::hash<0>; hashfuncs[1] = &CountSketch<C>::hash<1>; // ... for all i until i==T which is known at compile time }; private: template<int offset> size_t hash(C &c) { return (reinterpret_cast<int>(&c)+offset)%B; } size_t (CountSketch::*hashfuncs[T])(C &c); };
I would thus like to know if I can do a loop to initialize the T hash functions using a loop. The bounds of the loops are known at compile time, so, in principle, I don't see any reason why it couldn't be done (especially since it works if I unroll the loop manually).
Of course, in this specific example, I could just have made a single hash function with 2 parameters (although it would be less efficient I guess). I am thus not interested in solving this specific problem, but rather knowing if "compile time loops" existed for similar cases.
Thanks!
In general, for loops can't be compile -time evaluated.
All the template parameters are fixed+known at compile-time. If there are compiler errors due to template instantiation, they must be caught at compile-time!
If we have to wait for the compilation part, that slows down the entire workflow. And time is money. If one manages to optimise the compilation time down to a few milliseconds, then we can move on to testing our changes. If we need to wait hours until that step, that creates a bottleneck in the development.
A compile-time constant is a value that is computed at the compilation-time. Whereas, A runtime constant is a value that is computed only at the time when the program is running. 2. A compile-time constant will have the same value each time when the source code is run.
Nope, it's not directly possible. Template metaprogramming is a pure functional language. Every value or type defined through it are immutable. A loop inherently requires mutable variables (Repeatedly test some condition until X happens, then exit the loop).
Instead, you would typically rely on recursion. (Instantiate this template with a different template parameter each time, until you reach some terminating condition).
However, that can solve all the same problems as a loop could.
Edit: Here's a quick example, computing the factorial of N using recursion at compile-time:
template <int N> struct fac { enum { value = N * fac<N-1>::value }; }; template <> struct fac<0> { enum { value = 1 }; }; int main() { assert(fac<4>::value == 24); }
Template metaprogramming in C++ is a Turing-complete language, so as long as you don't run into various internal compiler limits, you can solve basically any problem with it.
However, for practical purposes, it may be worth investigating libraries like Boost.MPL, which contains a large number of data structures and algorithms which simplify a lot of metaprogramming tasks.
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