简体   繁体   中英

Instantiation of array class of size unknown at compile time

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.

  1. 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, ie a user input, you can't use this solution at all.

    So this is not a good option here.

  2. 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!

You can use a vector instead;

#include <vector>

vector<int> myArray (n); // n zero-initialized elements

use the operator[] like you are using the array.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM