1

I have a global array of size DIMENSIONS: DIMENSIONS is a static global variable. I can change the hardcoded DIMENSIONS variable without issues in compilation or execution, but is there a way to determine this value at compile time versus run time?

const static unsigned int DIMENSIONS = 2;
std::array<double, DIMENSIONS> arr;

// ...
// ...
// ...

int main (int argc, char* argv[]) {
    // argv[1] contains value '4'
}

If I made DIMENSIONS non-constant non-static, is there a way to reinitialize it as argv[1] in main() and have arr still instantiate properly? An idea of what I'd like to accomplish:

unsigned int DIMENSIONS;
std::array<double, DIMENSIONS> arr;

// ...
// ...
// ...

int main (int argc, char* argv[]) {
    DIMENSIONS = atoi(argv[1]);
}

I'd like to control the dimensionality of my program (it's meant for hill climbing optimization) through the command line. I understand arrays cannot have dynamic sizing and besides VLAs, must have their size declared at compile time, not run time. I specifically need a global non-VLA, though.

gator
  • 3,465
  • 8
  • 36
  • 76
  • 5
    `std::vector` . – tkausl Nov 23 '19 at 23:48
  • 3
    Short answer: no there isn't. C++ does not work this way. This is what `std::vector` is for. – Sam Varshavchik Nov 23 '19 at 23:52
  • 1
    You seem to have answered your own question: _"I understand arrays [...] must have their size declared at compile time, not run time."_ Yet you still ask if you can have their size set at run time, not compile time? – JaMiT Nov 24 '19 at 00:30

2 Answers2

4

No, that is in general impossible.

First off you need to know all instantiations of a template at compile-time. If you are not intend on instantiating std::array<double, DIMENSIONS> for each value of DIMENSIONS that could be used, then this already disqualifies any solution.

Even if you have instantiated for every possible value of DIMENSIONS, you cannot have the global static std::array object have its size change.

In principle you could placement-new an object of different std::array type into the storage occupied by arr, but this would then require declaring it already with the size of the largest value allowed for DIMENSIONS to begin with and it would also require carrying around the size of the array in order to access it with the correct type everywhere and making every code accessing it conditional on that.

C++17 offers std::variant which encapsulates this, but with only C++11 it is not going to look nice (at least without some help from boost), so I skip that.

But in the end it is going to be way too complicated and will generate very large binaries. You should simply use std::vector instead of std::array.

If you want to allow arbitrary values for DIMENSIONS, then this will be impossible.

walnut
  • 21,629
  • 4
  • 23
  • 59
1

That's a really interesting question. However, the answer is no.

C arrays and std::arrays have their sizes known/constructed at compile time. argv and argc aren't known until run-time. There's really no exceptions, and trying use a size only known at run-time anyway can have some really bad results.

If you want an array with a variable size length in C++, these are your options.

I'm not sure I understand what you mean by "I specifically need a global non-VLA, though." but if you're implying you need an std::array specifically for some reason, you can copy the elements of a std::vector into a std::array, but note that you're still stuck at knowing the size of these std::arrays at compile time.

Also note that a std::vector will work just as well as a std::array in most cases unless an API function specifically accepts a std::array or something weird like that.