0
votes

I have two macros:

#define length(array) sizeof(array)/sizeof(array[0])
#define randRange(x,y) x + ( std::rand() % ( y - x + 1 ) )

I Can do this:

int data[] = {2, 3, 34, 10, 3, 12, 30 };
const int arr_length = length(data);
std::array<int,arr_length> data_std_array;

I Can initialize with a constant:

const int arr_length = 500;
std::array<int,arr_length> data_std_array;

But I can't initialize an std::array with my rand function:

float a = randRange(2, 200);
const int arr_length = (int)a;
std::array<int,arr_length> data_std_array;

float a = randRange(2, 200);
int counter = 0;
for(int i =0; i < a; i++){
    counter++;
}
const int arr_length = counter;
std::array<int,arr_length> data_std_array;

float a = randRange(2, 200);
const int arr_length = static_cast<int>(a);

None of these work.

I've tried all sorts of variables like size_t and unsigned ints, constants, pointers etc. I always get this error message

Error msg I always receive: float a = randRange(2, 200); const int arr_length = static_cast(a);

/home/martin/Documents/github/on-line-mean-calculation/tests/test.cpp: In member function ‘virtual void algorithmTest_TestAlgorithmRandomArray_Test::TestBody()’:
/home/martin/Documents/github/on-line-mean-calculation/tests/test.cpp:87:20: error: the value of ‘arr_length’ is not usable in a constant expression
     std::array<int,arr_length> data_std_array;
                    ^
/home/martin/Documents/github/on-line-mean-calculation/tests/test.cpp:76:15: note: ‘arr_length’ was not initialized with a constant expression
     const int arr_length = static_cast<int>(a);
               ^
/home/martin/Documents/github/on-line-mean-calculation/tests/test.cpp:87:30: error: the value of ‘arr_length’ is not usable in a constant expression
     std::array<int,arr_length> data_std_array;
                              ^
/home/martin/Documents/github/on-line-mean-calculation/tests/test.cpp:76:15: note: ‘arr_length’ was not initialized with a constant expression
     const int arr_length = static_cast<int>(a);
               ^
/home/martin/Documents/github/on-line-mean-calculation/tests/test.cpp:87:30: note: in template argument for type ‘long unsigned int’ 
     std::array<int,arr_length> data_std_array;

How can I initialize and std array with a random length in range?

2
The short answer: you can't. std::array's size is a compile time constant. Pretty sure it's very difficult to derive a compile-time constant from some random value that's determined at run-time.Sam Varshavchik
Yeah, you definitely can make a compile-time pseudo-random number generator (I challenge you to replicate std::mt19937 :P), seed it with e.g. __TIME__ and get the value from it.HolyBlackCat
Why do you want a compile-time size? Why not std::vector?HolyBlackCat
Compile time size - std::array, run time size - std::vector.Bo Persson
By the way, in C++17, there is std::size that should be used instead. See en.cppreference.com/w/cpp/iterator/size.Phil1970

2 Answers

3
votes

No; array's length must be a compile time constant, and there are no compile time random number engines in std C++ library.

If you want a runtime determined contiguous buffer of data, use std::vector. That it what it is for, and what it does.

If you want a non-std random number compile-time constant, choose 4. I rolled it using a fair die.

In theory you could use macros that encode the compile time of your code and write a compile time pseudo-random number generator based on that. Or you could use continuation passing style and templated code with a bound to compile some large number K of programs and choose which one to execute at runtime. But all of these are quite frankly bad ideas.

Heck, you could make your C++ program print a C++ program to a file, include a C++ compiler in your program, link against the output of the program you print dynamically, and run that code.

3
votes

A std::array has a compile-time size. That means that, no matter what you do with it, every time you run the program, it will create an array with the same number of elements. If that's not what you want, you should look into std::vector, which can change size at run-time, so it can be different every time you run the program.

Either way, you shouldn't create macros unless they are necessary. Sometimes they are, but usually (including in these cases), they cause more problems than they solve and you should use functions instead. Both your length and randRange macros are better implemented as functions, and length already exists as std::size.

Run-Time Random Number Generation

If you want run-time random numbers, which are what people usually want when talking about randomness, you should use the C++ randomness library, not the rand function inherited from C. However, it can be difficult to use unless you know a lot more than most programmers want to bother learning about random numbers; I'd recommend using some library based on it that's easier to use, like the randutils library.

Compile-Time Random Number Generation

If, for some reason, you want to generate a random number at compile time, so that every time you run the program you get the same number but if you recompile you get a different one, that is possible in C++11 and later. There's a C++ Weekly video about this topic, and other examples you can find online.