2

I have a constexpr size_t array whose members will be passed to the template parameters of a class that gets initialized, iterating over the array to construct and use several differently templated objects. Here's the general idea:

template <size_t N>
class Foo
{
    // magic
};

constexpr size_t c_arr[] = { 2, 5, 3, 2 };

for (int i = 0; i < 4; i++)
{
    Foo<c_arr[i]> foo;
    foo.bar();
}

However, this will raise the following error:

templ_arr.cpp: In function ‘int main()’:
templ_arr.cpp:56:21: error: the value of ‘i’ is not usable in a constant expression
         Foo<c_arr[i]> foo;
                     ^
templ_arr.cpp:51:14: note: ‘int i’ is not const
     for (int i = 0; i < 3; i++)
              ^
templ_arr.cpp:56:20: note: in template argument for type ‘long unsigned int’
         Foo<c_arr[i]> foo;

I can't seem to find a way to use const_cast on i to allow it to be used inside the parameter, nor can I do something like this to get around it, as it gives me the same error:

for (int i = 0; i < 4; i++)
{
    const int j = i;
    Foo<c_arr[j]> f;
    foo.bar();
}

What am I doign wrong, and how can I get around this?

OakenDuck
  • 485
  • 1
  • 6
  • 15
  • 1
    The for loop can't be used at compile time, it is totally a runtime stuff. You are trying to evaluate a `for` expression that's why you got the error. – Yves Jun 25 '21 at 04:09
  • 1
    You see, things like `if` and `for` are runtime stuff. In c++17, we have `if constexpr`, which can play `if` at compile time. But we haven't had things like `for constexpr` or `for(constexpr int ...)`. – Yves Jun 25 '21 at 04:16
  • 1
    Does this answer your question? [Why isn't a for-loop a compile-time expression?](https://stackoverflow.com/questions/37602057/why-isnt-a-for-loop-a-compile-time-expression) – Yves Jun 25 '21 at 04:18
  • There are ways of implementing a `for` loop using template meta programming. If you can post in detail how you intend to use such a loop, someone might be able to help you. Example: https://stackoverflow.com/questions/46871005/how-to-unroll-a-for-loop-using-template-metaprogramming – R Sahu Jun 25 '21 at 04:21
  • 1
    You need to show more details of what the loop is supposed to accomplish. There are probably ways to work around this, but without more information it's just a guessing game. – super Jun 25 '21 at 04:45

1 Answers1

3

If you want values to be used as template parameter, use std::integer_sequence

template <size_t N>
class Foo
{
 public:
  void bar() {}
};

template<std::size_t ...I>
void foo_bar(std::index_sequence<I...>) {
  int dummy[] = { (Foo<I>{}.bar(), 0) ... };
  // ((Foo<I>{}.bar()), ...); if using C++17 or above
}

int main() {
  constexpr std::index_sequence<2, 5, 3, 2> id;

  foo_bar(id);
}
김선달
  • 1,485
  • 9
  • 23