Below is a small script that prints the sums of the numbers 1 to n, for n = 1,...,20.
#include <iostream>
#include <array>
using namespace std;
int test(int n)
{
array<int,n> myArray;
for (int iii = 0; iii < n; iii++)
myArray[iii] = iii+1;
int nSum;
for (int iii = 0; iii < n; iii++)
nSum += myArray[iii];
return nSum;
}
int main()
{
for (int n = 1; n <= 20; n++)
cout << test(n) << endl;
return 0;
}
Of course, this won't compile:
Main.cpp: In function ‘int test(long unsigned int)’:
Main.cpp:9:13: error: ‘n’ is not a constant expression
array<int,n> myArray;
^
Main.cpp:9:13: note: in template argument for type ‘long unsigned int’
Main.cpp:9:22: error: invalid type in declaration before ‘;’ token
array<int,n> myArray;
^
Main.cpp:11:26: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for (int iii = 0; iii < n; iii++)
^
Main.cpp:12:14: error: invalid types ‘int[int]’ for array subscript
myArray[iii] = iii+1;
^
Main.cpp:16:26: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for (int iii = 0; iii < n; iii++)
^
Main.cpp:17:22: error: invalid types ‘int[int]’ for array subscript
nSum += myArray[iii];
^
make: *** [Main.o] Error 1
The problem seems to be (among other things) that n
isn't a constant expression, and I get why that is a problem, but I have no idea how to solve it.
I know how to instantiate "regular" arrays with the new function, but I don't understand how it is possible with the array class.
How do I make the test
function treat n
as a constant?
You have basically two options.
As you already mentioned, std::array
needs a compile-time size. So make it known at compile-time! This can be done by converting it to a template parameter.
Change
int test(int n)
{
.
.
.
}
to
template<int n>
int test()
{
.
.
.
}
The problem is that it then has to be called with test<n>()
instead of test(n)
and this again requires the n
in the caller code to be known at compile-time, too, which is not the case with a for
-loop. If you know your loop's upper bound during compile-time (like in your current code snippet), it can be done, but it's a bit complicated. And if it's not known, i.e. a user input, you can't use this solution at all.
So this is not a good option here.
Don't use std::array
but a container type which doesn't require the size at compile-time but during runtime. A heap-allocated raw array (new int[n]
), as you mentioned, is an option, but it's not very C++-ish. Use std::vector
instead!
For this, simply change
array<int,n> myArray;
to
vector<int> myArray(n);
PS. In the future, there probably will be std::dynarray
(proposed container type) which fits exactly that purpose a bit better than std::vector
currently does. It's reflecting the purpose of new int[n]
where n
is known at runtime but constant during the lifetime of the array, filling the gap between std::array
and std::vector
. Yet in almost all cases std::vector
will do just fine!