convert variable to const - c++

I have an array that i dont know it size till run time. Once the program starts and size is computed, the size won't change.
i tested the following code:
#include <iostream>
#include <boost/array.hpp>
#include <cstdint>
int main()
{
uint32_t num_bits = 12;
const uint32_t num_elements = 1 << num_bits;
boost::array<double, num_elements > myArray; //does not work
return 0;
}
the following code doesn't work since num_elements is computed. I saw that there are "const_cast" option, but i am not sure if it will solve my problem.
I would apprichiate if there is a boost solution, since i would like to use boost::array.
EDIT
num_bits is a parameter which i read from a file, this mean also unknown before run time. I am aware of the solution using std::vector, but access speed is also important, since i access those elements frequently and my simulation takes about 3 days... At the moment i use simply array (new and delete)

Boost array is for arrays whose size is known at compile time. Its arguments have to be constant expressions.
Use std::vector or similar container.
Although your example doesn't need to be calculated at run time:
const uint32_t num_bits = 12; // mark this const too
const uint32_t num_elements = 1 << num_bits;
boost::array<double, num_elements > myArray;

Can't you use std::vector instead of boost::array? The size of a std::vector can be computed at runtime.
The const_cast only converts a variable to/from const at runtime as well, it can't be used to create a constant at compile-time, which boost::array (and the new C++11 std::array) wants.

Argument to any template should be a compile time constant (or type). If you know num_bits at compile time then use it as compile time constant:
boost::array<double, (1 << num_bits)> myArray; //ok
If the size is not known at compile time then use dynamically allocated arrays or std::vector.

Related

How do I create a C++ Integer Array of constant length?

I am quite an experienced python programmer, attempting to learn C++. I am having an issue with initialising an integer array of a fixed size.
I have read this but creating my integer as a constant has not fixed my issue. What am i missing here?
BTW i am using VS2019 Community, any help would greatly be appreciated!
#include <iostream>
#include <sstream>
int numericStringLength(int input) {
int length = 1;
if (input > 0) {
// we count how many times it can be divided by 10:
// (how many times we can cut off the last digit until we end up with 0)
for (length = 0; input > 0; length++) {
input = input / 10;
}
}
return length;
}
int convertNumericStringtoInt(std::string numericString) {
std::stringstream data(numericString);
int convertedData = 0;
data >> convertedData;
return convertedData;
}
int main() {
std::string numericString;
std::cout << "Enter the string: ";
std::cin >> numericString;
const int length = numericStringLength(convertNumericStringtoInt(numericString));
std::cout << "Length of Numeric string: " << length << "\n";
int storage[length];
}
but creating my integer as a constant has not fixed my issue
It is not sufficient for the array length to be const. It must be compile time constant. const merely means that the object does not change throughout its lifetime - i.e. it implies runtime constness. Since length is not a compile time constant, the program is ill-formed. Examples of values that are compile time constant:
Literals such as 42
Template arguments
Enumerations
constexpr variables
const variables with compile time constant initialiser (this may have some limitations, I'm not sure)
It should be quite clear from the program that the length is calculated from user input, which would be impossible to do when the program is compiled. So since you cannot make it a compile time constant, you cannot use an array variable. You need to allocate the array dynamically. Simplest solution is to use a vector:
std::vector<int> storage(length);
Making the variable const is not enough.
const just means "I won't change this after it's initialised".
It has to be a compile-time constant, as the machinery for a basic C array is baked into the computer instructions that form your executable.
You're calculating it at runtime, so there's no way that is going to work.
You are going to have to use a vector or some other such dynamically-resizable array type.
If you want a fixed size array, you can use std::array, example:
std::array<int, 3> arr { 1,2,3 };
// ^
// fixed size needs to be known at compile time
If you don't know the size at compile time, use std::vector
The problem you have is that length is a run-time constant, whose value is calculated when the program is running. This is opposed to a compile-time constant, whose value is known by the compiler when you build your program.
Arrays needs compile-time constants for their size.
If the size is not known at compile-time but only at run-time, then you should use std::vector.

Assign instance of 2d array to index in 3d array

I have a 2d and 3d array declared as follows:
unsigned char twoDArray[2][2];
unsigned char threeDArray[5][2][2];
I populated my "twoDArray" with the four values that I need, and now I want to place this into the first location of the threeDArray:
threeDArray[0] = twoDArray;
I am getting an error message of "Cannot assign to an array type unsigned char[2][2]." Is there any way to do this assignment, aside from looping through the 2d array and placing each value into the 3d array one at a time at location threeDArray[0][row][col] (where row and col change to access each element in my 2d array)?
Thanks in advance.
If you're using C++11, you can use std::array<> instead of c-style arrays which support assignment via operator=.
std::array<std::array<unsigned char, 2>, 2> twoDArray{};
The best solution to this really depends on, whenever you can use C++11 or not.
If you have to rely on pre C++11 you have to do this, like you would do this in C:
Using memcpy to copy the memory of the array into the other one. This is error prone, since it lacks type safety, so one wrong number and boom undefined behaviour.
With C++11 you can use std::array which makes everything easier, more readable and more safe, I made you a solution for both ways:
#include <cstring>
#include <array>
int main() {
{
unsigned char twoDArray[2][2];
unsigned char threeDArray[5][2][2];
std::memcpy(threeDArray[0], twoDArray, 2 * 2);
}
{
using oneDArrayT = std::array<unsigned char, 2>;
using twoDArrayT = std::array<oneDArrayT,2>;
twoDArrayT twoDArray{};
std::array<twoDArrayT,5> threeDArray{};
threeDArray[0] = twoDArray;
}
}

Why can I declare a 2D array with both dimensions sized variable but not new one?

As the problem stated, this is doable:
#include <iostream>
int main(int argc, char *argv[])
{
unsigned short int i;
std::cin >> i;
unsigned long long int k[i][i];
}
Here I declared an array that is sized i by i, both dimensions are variables.
But not this:
#include <iostream>
int main(int argc, char *argv[])
{
unsigned short int i;
std::cin >> i;
unsigned long long int** k = new int[i][i];
delete[] k;
}
I got an compiler message telling me that
error: only the first dimension of an allocated array may have dynamic
size
I am forced to do this:
#include <iostream>
int main(int argc, char *argv[])
{
unsigned short int i;
std::cin >> i;
unsigned long long int** k = new unsigned long long int*[i];
for ( unsigned short int idx = 0 ; idx < i ; ++ i )
k[idx] = new unsigned long long int[i];
for ( unsigned short int idx = 0 ; idx < i ; ++ i )
delete[] k[idx];
delete[] k;
}
To my understanding, new and delete are used to allocate something on heap, not on stack, which won't be deleted when it goes out of scope, and is useful for passing datas across functions and objects, etc.
What I don't understand is what happens when I declare that k in the first example, I am told that declared array should (and could) only have constant dimensions, and when in need for a array of unknown size, one should always consider new & delete or vectors.
Is there any pros and cons to those two solutions I'm not getting, or is it just what it is?
I'm using Apple's LLVM compiler by the way.
Neither form is C++ standard compliant, because the standard does not support variable-length arrays (VLAs) (interestingly, C99 does - but C is not C++). However, several compilers have an extension to support this, including your compiler:
From Clang's Manual:
Clang supports such variable length arrays in very limited circumstances for compatibility with GNU C and C99 programs:
The element type of a variable length array must be a POD ("plain old data") type, which means that it cannot have any user-declared constructors or destructors, any base classes, or any members of non-POD type. All C types are POD types.
Variable length arrays cannot be used as the type of a non-type template parameter.
But given that the extension is in place, why doesn't your second snippet work? That's because VLA only applies to automatic variables - that is, arguments or local variables. k is automatic but it's just a pointer - the array itself is defined by new int[i][i], which allocates on the heap and is decidedly not an automatic variable.
You can read more about this on the relevant GCC manual section.
I'm sure you can find implementation for 2D array functionality easily, but you can make your own class too. The simplest way is to use std::vector to hold the data and have an index-mapping function that takes your two coordinates and return a single index into the vector.
The client code will look a little different, instead of arr[x][y] you have arr.at(x,y) but otherwise it does the same. You do not have to fiddle with memory management as that is done by std::vector, just use v.resize(N*N) in constructor or dimension-setting function.
Essentially what compilers generally do with two-dimensional arrays (fixed or variable) is this:
int arr[x][y] ---> int arr[x*y];
arr[2][4]= something ---> arr[2+4*x]= something;
Basically they are just a nicer way of notation of a one-dimensional array (on the stack). Most compilers require fixed sizes, so the compiler has an easier way of telling what the dimensions are (and thus what to multiply with). It appears you have just a compiler, which can keep track of the dimensions (and multipliers) even if you use variables.
Of course you can mimick that with new[] yourself too, but it's not supported by the compiler per se.
Probably for the same reason, i.e. because it would be even harder keeping track of the dimensions, especially when moving the pointers around.
E.g. with a new-pointer you could later write:
newarr= someotherarray;
and someotherarray could be something with even different dimensions. If the compiler did a 2-dim -> one dim translation, he'd have to track all possible size transitions.
With the stack allocated arr above, this isn't necessary, because at least once the compiler made it, it stays that size.

problem with sizeof operator

As i want to find array size dynamically in function, i used sizeof operator. But i got some unexpected result.
here is one demo program to show you, what i want to do.
//------------------------------------------------------------------------------------------
#include <iostream>
void getSize(int *S1){
int S_size = sizeof S1/sizeof(int);
std::cout<<"array size(in function):"<<S_size<<std::endl;
}
int main(){
int S[]={1,2,3,2,5,6,25,1,6,21,121,36,1,31,1,31,1,661,6};
getSize(S);
std::cout<<"array size:"<<sizeof S/sizeof(int)<<std::endl;
return 0;
}
//------------------------------------------------------------------------------------------
compilation command : g++ demo1.cc -o demo1 {fedora 12}
output:
array size(in function):2
array size:19
please explain ,why this is happening.
what can be done to solve this problem.
void getSize(int *S1)
When you pass an array to this function, it decays to pointer type, so sizeof operator will return the size of pointer.
However, you define your function as,
template<int N>
void getSize(int (&S1)[N])
{
//N is the size of array
int S_size1 = N;
int S_size2 = sizeof(S1)/sizeof(int); //would be equal to N!!
std::cout<<"array size(in function):"<<S_size1<<std::endl;
std::cout<<"array size(in function):"<<S_size2<<std::endl;
}
int S[]={1,2,3,2,5,6,25,1,6,21,121,36,1,31,1,31,1,661,6};
getSize(S); //same as before
then you can have the size of array, in the function!
See the demonstration yourself here : http://www.ideone.com/iGXNU
Inside getSize(), you're getting size of pointer, which is 8 bytes (since you're probably running 64-bit OS). In main(), you're getting size of array.
If you want to know array size, pass result of sizeof(S) as additional argument to getSize().
More alternatives would be using some container (like std::vector) or turning function into template function, as Nawaz proposed.
S is an int *, a pointer to an integer, which is a memory address, which is on your machine twice the size of an integer.
If you want the size of the array (I.e., the number of elements), you can't get that directly in pure C. But since this is a c++ question, there is a way: use a vector, which has a size() method.
Actually, this isn't quite true: within the function that you declare S (and only if it's explicitly initialized at compile time as you do in your example -- even new int[19] doesn't work), the sizeof operator actually does get the correct answer, which is why c++ allows you to do this:
int S[]={1,2,3,2,5,6,25,1,6,21,121,36,1,31,1,31,1,661,6};
vector<int> v(S, S + sizeof(S) / sizeof(int) );
and then you can use v.size() (see these docs).
The template version by Nawaz elsewhere is another excellent suggestion which forces the compiler into carrying the full information about the construction of the c++ array around (again, note that this is all known at compile time, which is why you can be explicit about the size in the argument).
you are getting the size of the pointer to the array. If you want the size of the array you have to multiply the number of elements by the size of each element.
You will have to pass the size of the array to the function.
Since you are only passing a pointer to the first element in the array, your function has no information on its actual size.
void getSize(int *S1, size_t size)
{
int S_Size = sizeof(*S1) * size;
}
This is redundant though, if you think about it :D
To prevent this type of accidental misuse of sizeof, you can define a function which only works on arrays:
template<class T, int N>
int array_size(T (&)[N]) {
return N;
}
If you use this in your code, you'll see a compiler error when applied to S1, as it is not an array. Plus, it's shorter and a bit more explicit than sizeof array / sizeof array[0] (using the size of the first item means you don't have to repeat the array type).
This also already exists in Boost in a more general form (accepting anything with a size method, such as std::vector).

How do I use member functions of constant arrays in C++?

Here is a simplified version of what I have (not working):
prog.h:
...
const string c_strExample1 = "ex1";
const string c_strExample2 = "ex2";
const string c_astrExamples[] = {c_strExample1, c_strExample2};
...
prog.cpp:
...
int main()
{
int nLength = c_astrExamples.length();
for (int i = 0; i < nLength; i++)
cout << c_astrExamples[i] << "\n";
return 0;
}
...
When I try to build, I get the following error:
error C2228: left of '.length' must have class/struct/union
The error occurs only when I try to use member functions of the c_astrExamples.
If I replace "c_astrExamples.length()" with the number 2, everything appears to work correctly.
I am able to use the member functions of c_strExample1 and c_strExample2, so I think the behavior arises out of some difference between my use of strings vs arrays of strings.
Is my initialization in prog.h wrong? Do I need something special in prog.cpp?
Arrays in C++ don't have member functions. You should use a collection like vector<string> if you want an object, or compute the length like this:
int nLength = sizeof(c_astrExamples)/sizeof(c_astrExamples[0]);
Just use STL vector of strings instead of array:
#include <string>
#include <vector>
using namespace std;
const string c_strExample1 = "ex1";
const string c_strExample2 = "ex2";
vector<string> c_astrExamples;
c_astrExamples.push_back(c_strExample1);
c_astrExamples.push_back(c_strExample2);
int main()
{
int nLength = c_astrExamples.size();
Arrays in C++ are inherited from C, which wasn't object-oriented. So they aren't objects and don't have member functions. (In that they behave like int, float and the other built-in types.) From that ancestry stem more problems with array, like the fact that they easily (e.g., when passed into a function) decay into a pointer to the first element with no size information left.
The usual advice is to use std::vector instead, which is a dynamically resizable array. However, if you the array size is known at compile-time and you need a constant, then boost's array type (boost::array, if your compiler supports the TR1 standard extensions also available as std::tr1::array, to become std::array in the next version of the C++ standard) is what you want.
Edit 1:
A safe way to get the length of an array in C++ involves an incredible combination of templates, function pointers and even a macro thrown into the mix:
template <typename T, std::size_t N>
char (&array_size_helper(T (&)[N]))[N];
#define ARRAY_SIZE(Array_) (sizeof( array_size_helper(Array_) ))
If you (like me) think this is hilarious, look at boost::array.
Edit 2:
As dribeas said in a comment, if you don't need a compile-time constant, this
template <typename T, std::size_t N>
inline std::size_t array_size(T(&)[N])
{return N;}
is sufficient (and much easier to read and understand).
c_astrExamples is an array, there is no "length()" method in it.
In C++ arrays are not objects and have no methods on it. If you need to get the length of the array you could use the following macro
#define COUNTOF( array ) ( sizeof( array )/sizeof( array[0] ) )
int nLength = COUNTOF(c_astrExamples);
Also, beware of initialisation in a header file. You risk offending the linker.
You should have:
prog.h:
extern const string c_strExample1;
extern const string c_strExample2;
extern const string c_astrExamples[];