Reputation: 90
possibly silly question: I am trying to do the following
template<unsigned int N>
class Foo{...}; // Define class Foo accordingly
int main(){
for (unsigned int i = 0; i < 10; i++){
Foo<i> f(3);
f.show();
}
return 0;
}
As you can imagine, it won't compile since the variable i
is not const
. I know the reason for this is that the values assigned inside the non-type template argument Foo<i>
must be known at compile time and since this is not the case here, it doesn't really know what to do. Now, I was wondering if there is a way to overcome this problem. First idea is, of course, to declare unsigned int N
as member-variable of class Foo.
So question: Is it possible to achieve the desired behaviour above using template arguments, or do I have to declare unsigned int N
as member variable of my class?
P.S.: I've tried to find a related to question, but the questions I've found were related to how to use non-type template parameters, where they didn't quite answer the question. Since they didn't mention that this is possible I assume this can't be done...
Edit.
Is it possible to do the following?
template<unsigned int N>
class Foo{...}; // Define class Foo accordingly
int main(){
std::vector<Foo> v; // I know it's better with shared_ptr, etc.. but to get the idea..
for (unsigned int i = 0; i < 10; i++){
Foo<i> f(3);
f.show();
v.push_back( f );
}
return 0;
}
Upvotes: 3
Views: 87
Reputation: 26282
We don't have for constexpr
in the language, so you can't do it directly. You have to somehow emulate a compile-time for
loop. There are several options.
Use std::integer_sequence
(C++14) and int...
pack:
template<int i>
void foo() {
Foo<i> f(3);
f.show();
}
template<int... is>
void foo(std::integer_sequence<int, is...>) {
(foo<is>(), ...); // expands into foo<0>(), foo<1>(), ..., foo<9>()
}
foo(std::make_integer_sequence<unsigned int, 10>{});
Use recursion and if constexpr
(C++17) to emulate a for
loop:
template<unsigned int i>
void foo()
{
Foo<i> f(3);
f.show();
if constexpr (i + 1 < 10)
foo<i + 1>();
}
foo<0>();
Use std::integral_constant
(C++11) and function overloading:
void foo(std::integral_constant<unsigned int, 10>) {}
template<unsigned int i>
void foo(std::integral_constant<unsigned int, i>) {
Foo<i> f(3);
f.show();
foo(std::integral_constant<unsigned int, i + 1>{});
}
foo(std::integral_constant<unsigned int, 0>{});
Foo<i>
and Foo<j>
are distinct types for distinct i
and j
. You can't put distinct types into a std::vector
. If i
s are known at compile-time, you can make a std::tuple
of Foo<i>
s. But this still would employ some template tricks.
Upvotes: 4