2

I want to write a load of lines into a C++ file of the form foo(i) for i = 0,1, ... , n, is there a way of doing this at compile time?

I want to do this because I've got a templated class:

template <int X> class MyClass{ ... }

and I want to test it for lots of different values of "X" with something like:

for (int i = 0; i < n; i++) {
    MyClass<i> bar;
    bar.method()
 }

This doesn't work as it wants the value passed as the template value to be determined at compile time.

I could write out the whole thing:

MyClass<0> bar0; bar0.method();
MyClass<1> bar1; bar1.method();

and I could make a define to speed it up a bit, something like:

#define myMacro(x) MyClass<x> bar_x; bar_x.method();

but I'd still have to write myMacro everywhere and I'm going to want to change the range too often for this to be sensible. If I could write some sort of macro version of a for loop it'd save me a lot of time.

Update: I actually needed to pass variables to my method so I made slight changes to the accepted answer given by @Pascal

template<int X> class MyClass { public: void foo(int Y) { std::cout << X Y<< std::endl; } };
template<int X> inline void MyTest(int Y) { MyTest<X - 1>(Y); MyClass<X-1> bar; bar.foo(Y); }
template<> inline void MyTest<1>(int Y) { MyClass<0> bar; bar.foo(Y); }
R.Mckemey
  • 335
  • 1
  • 3
  • 14
  • 1
    related/ maybe dupe: https://stackoverflow.com/questions/6872919/compile-time-loops – NathanOliver Aug 18 '17 at 14:04
  • Wyy do you need the integral value to be a template parameter (determined at compile time) instead of a function argument (determined at run time)? – Peter Aug 18 '17 at 14:31
  • @Peter it's because I'm testing the code. Given the chance I'd re-write it so that it's a functions taking a run time argument, but it's important for external reasons that the code isn't touched. – R.Mckemey Aug 18 '17 at 16:02

2 Answers2

2

A solution closer to the "macro way" can be the template recursivity :

template<int X> class MyClass { public: void foo() { std::cout << X << std::endl; } };
template<int X> inline void MyTest() { MyTest<X - 1>(); MyClass<X-1> bar; bar.foo(); }
template<> inline void MyTest<1>() { MyClass<0> bar; bar.foo(); }
int main()
{
    MyTest<5>();
    return 0;
}

And the output of this example is :

0
1
2
3
4
Pascal
  • 142
  • 3
  • It's not a "macro way", The way to do compile-time looping with templates is to use recursion like this. – Peter Aug 18 '17 at 14:54
  • The problem with this solution that it does recursive macro instantiation, which is not necessary and slows down compilation. – SergeyA Aug 18 '17 at 16:38
  • @Pascal : declaring a function inline does not guarantee that the compiler will inline it. – Sapphire_Brick May 03 '20 at 01:54
0

Provided your loop threshold is known at compile time, this is uber easy:

template<class CB, size_t... Is> void unroll_loop_impl(std::index_sequence<Is...> {}, CB&& cb) {
    void* aux[] = {(cb(Is), nullptr)...};
    (void)aux;
}


template<size_t N, class CB> void unroll_loop(CB&& cb) {
     using index_seqeunce_t = std::make_index_sequence<N>;

     unroll_loop_impl(std::move(cb), index_sequence_t{});
}
SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • I do know the loop threshold at compile time but I'm sorry, I don't understand this solution. I don't see how your variables link to the ones I'm trying to work with and I'm not familiar with some of the std functions you're using. I guess the general principle is to make a templated class which is passed a class to unroll? – R.Mckemey Aug 18 '17 at 16:32
  • @SergeyA - You consider this "uber easy", but the OP clearly doesn't understand it. You may wish to explain how it works to address the OP's problem. – Peter Aug 18 '17 at 21:47