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?

5
  • 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. Commented Jun 25, 2021 at 4: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 ...). Commented Jun 25, 2021 at 4:16
  • 1
    Does this answer your question? Why isn't a for-loop a compile-time expression? Commented Jun 25, 2021 at 4: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: stackoverflow.com/questions/46871005/… Commented Jun 25, 2021 at 4: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. Commented Jun 25, 2021 at 4:45

1 Answer 1

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);
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.