0

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?

15
  • 7
    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. Commented Mar 31, 2018 at 19:49
  • 6
    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. Commented Mar 31, 2018 at 19:53
  • 5
    Why do you want a compile-time size? Why not std::vector? Commented Mar 31, 2018 at 19:58
  • 2
    Compile time size - std::array, run time size - std::vector. Commented Mar 31, 2018 at 20:18
  • 2
    By the way, in C++17, there is std::size that should be used instead. See en.cppreference.com/w/cpp/iterator/size. Commented Mar 31, 2018 at 20:59

2 Answers 2

3

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.

Sign up to request clarification or add additional context in comments.

4 Comments

Can I make a vector ... and convert it to a std::array ?
@hartun Yes, but not in the way I think you are asking.
@Yakk I would go with "no", in the general case. Once the program is compiled only certain instantiations of std::array are actually in the source code. At that point it is impossible to make one for a size that doesn't exist without shelling out to the compiler and dynamically loading a new module or something equally bad.
@DanielH "No" except if you do insane things is the same as "Yes" but not in the way you are asking. ;) I can think of a bunch of ways to do it with vary in evil from compiling code and dynamically loading it, hacking binaries, to creating N template versions of your code and dispatching to which one at run time. Hence "Yes". Almost anything can be done. This is the Turing Tar Pit.
3

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.