Error: "Expression must have a constant value" - c++

I don't know if it's because I don't need it int the header of the function, but when I do int ticketClass, and int ticketAmount, and put them in the array, it says that the array must have a constant value, when to me at least it seems to already have one, I'm new to arrays and don't know what I did wrong, I appreciate any help I can get.
void customerData(int const CUSTOMERINFO[])
{
int const CUSTOMERINFO = 2;
int ticketClass[CUSTOMERINFO];
int ticketAmount[CUSTOMERINFO];
string moreTickets;
string customerChoice;
int i = 0;

That's not the error. The error is that you're declaring a new variable with the same name as the argument. See here
To fix this, choose a different name. From context here, perhaps CUSTOMER_COUNT or CUSTOMER_LIMIT.

Related

how to read this declaration int (*(*f2)(int n))[3];

I got this declaration from https://en.cppreference.com/w/cpp/language/scope, but don't know how to parse this declaration even there is a comment below.
my questions is
how to parse the declaration statement (I see it as a function pointer to a function protocol like "int[3] foo(int n)" or "int foo(int n)[3] --- they are illegal in C++ )? Then, how can I construct a concrete function which can be assigned to this function pointer? Thanks.
const int n = 3;
int (*(*f2)(int n))[n]; // OK: the scope of the function parameter 'n'
// ends at the end of its function declarator
// in the array declarator, global n is in scope
// (this declares a pointer to function returning a pointer to an array of 3 int
It's a pointer to a function taking an int and returning a pointer to an int array of size three.
All the comment is saying is that there are two n identifiers in play here. The [n] (in array declarator) is using the const int 3, not the parameter to the function (which is in the function declarator).
Starting in the middle, with each segment being included in the subsequent bullet point as ...:
f2 is a pointer, (*f2).
It's a pointer to a function taking an integer, ...(int).
It returns a pointer to an int array of size three, int (*...)[3].
You can form a concrete function for it as per the following complete program, which output the first element, 42:
#include <iostream>
const int n = 3;
int (*(*f2)(int n))[n];
int (*g2(int))[n] {
static int x[::n] = { 42 }; // Use outer n, not the parameter.
return &x; // since C++ has no VLAs. This
// means parameter is not actually
// needed in this test case, though
// it may be in more complicated
// tests.
}
int main() {
f2 = &g2; // Assign concrete function to pointer.
auto y = f2(3); // Call via pointer, get array.
std::cout << *(y[0]) << '\n'; // Deref first element to get 42.
}
Having said that, I would be rather curious if one of my colleagues submitting something like that for a code review, at least without a large comment explaining it. Although seasoned developers may be able to work it out, those less experienced may have trouble.
And, in fact, even seasoned developers shouldn't have to work it out, especially given it took me a few minutes.
C++ has a very expressive type system which can easily build something like this up in parts, so you don't have to experience migraines trying to work it out. For something like this, I'd be using std::vector (or std::array) unless there was a compelling case for the added complexity caused by more basic types.
You can create a type for pointer to an array of 3 int
typedef int (*array_with_size_n)[n];
and then use it as return type
const int n = 3;
int (*(*f2)(int n))[n];
int arr[n];
array_with_size_n func(int n)
{
return &arr;
}
int main()
{
f2 = &func;
return 0;
}

C++: Expression must have a constant value when declaring array inside function [duplicate]

This question already has answers here:
How do I use arrays in C++?
(5 answers)
Closed 6 years ago.
I have looked at all the other posts with a similar topic, and none help, so please don't flag as a duplicate.
I am defining in main() a const int SIZE = 20;. Then, I pass this as an argument to my function, Mode:
int* Mode(int* numbers, int & mode, const int SIZE)
{
int occurences[SIZE];
// Calcualte mode
}
However, I get the error, expression must have a constant value.
My function call (in main) looks like this:
int* occurencesPtr = Mode(numbersPtr, mode, SIZE);
With SIZE being defined at the beginning to the literal 20.
I understand that the error is because the function's version of SIZE only acquires its value when the function is called (?), but I don't know how I could work around this.
I have even tried passing to the function a const int * const SIZEPtr = &SIZE, but that didn't work either. Help?
EDIT: I am not trying to use a variable size!! Notice that I have made SIZE a const everywhere! I just want to use that same SIZE constant to declare my array.
EDIT: Dynamic arrays are not what I need. I just want a normal, named, array, defined with a constant size value passed to the function.
There is a misconception here with what const means, probably because it's a little confusing that this works:
const int SIZE = 20;
int array[SIZE];
but this doesn't:
void foo(const int SIZE) {
int array[SIZE];
// ...
}
const int SIZE = 20;
foo(SIZE);
The issue is that the array size in an array declaration must be a core constant expression. Simplified, that means an expression that's evaluatable at compile time to be a constant. That is true in the first case (you can see that SIZE is the integral constant 20) but that is not true in the second case. There, the SIZE function parameter is just const - in the sense that it is nonmodifiable - and not a core constant expression. You can see the difference in that I can call foo() with something that is clearly unknowable until runtime:
int x;
if (std::cin >> x) {
foo(x);
}
In order to pass an argument into foo, and have that argument be used as an array bound, it is not enough to have it be const - the actual integral value must be encoded into the type (unless you call foo() as constexpr which I'm assuming is not the case here). In which case, you'd have to do something like:
template <int SIZE>
void foo() { ... }
const int SIZE = 20;
foo<SIZE>();
or:
template <int SIZE>
void foo(std::integral_constant<int, SIZE > ) { ... }
const int SIZE = 20;
foo(std::integral_constant<int, SIZE>{} );
or simply have SIZE be a global constant or otherwise accessible to foo() in a way that doesn't have to do with its arguments.
Or, there's always the simple option: use std::vector:
void foo(const int SIZE) {
std::vector<int> v(SIZE);
...
}
I understand that the error is because the function's version of SIZE only acquires its value when the function is called (?), but I don't know how I could work around this.
Option 1
Instead of defining SIZE in main, add a constexpr function. Use the constexpr function instead of passing the size.
constexpr int getSize()
{
return 20;
}
int* Mode(int* numbers, int & mode)
{
int occurences[getSize()];
// ...
}
Option 2
Use std::vector instead of array.
int* Mode(int* numbers, int & mode, int size)
{
std::vector<int> occurences[size];
// ...
}
Option 3
Use a function template.
template <size_t SIZE>
int* Mode(int* numbers, int & mode, int size)
{
int occurences[SIZE];
// ...
}
Option 4
Use a function template and std::array.
template <size_t SIZE>
int* Mode(int* numbers, int & mode, int size)
{
std::array<int, SIZE> occurences;
// ...
}
You're confusing things. A constant expression has nothing to do with const (at least not that much) ;).
let's think we are the compiler and face this function:
void foo(const int SIZE) { }
The constmerely says "we are not able to change the function-local variable SIZE inside the function body.
We need to compile it without assuming that SIZE is compile time constant. Why?
Because there is noone stoping us from doing something like:
int i{};
std::cin >> i;
foo(i);
You can pass any (matching/convertible) value to a by value const function argument.
What should happen when the compiler assumed the value passed to foo was a compile time constant expression?
If you want to pass compile time constants, use templates and while you're at it use std::array instead of T[N]:
template<std::size_t N>
void foo()
{
std::array<int, N> occurences;
}
const isn't doing what you think it's doing in your Mode function.
When const is used in function definition, const is simply telling the compiler that the function will not change the argument declared const inside of the scope of it's function. But that does not make the argument a constant, it is actually called a constant expression. Some compilers enforce this, others do not, and so will allow you to change const expressions (arguments passed with const keyword).
In order to use a globally accessible constant value which you can use, like SIZE, you'll need to declare a global constant before the function is called; which could be declared outside of main(), or at least outside the scope of all other functions but main(), if you must declare all inside main. Pass the global constant to the Mode function just as you would any other variable.
Oh, and, main() needs a return type.
I've edited the code to meet your specific constraints.
Here is a variation on your original code:
int main(){
//Declare constants first.
const int SIZE = 20; /*Could declare here instead.*/
//Declare variables next.
int *intPtr = 0; // to hold the pointer passed from Mode.
int *numbersPointer = 0;
int mode = 0;
//Define Mode (using OP's code.)
int* Mode(int* numbers, int & mode, const int size){
int occurences[size];
// Calculate mode
}
/*Now use constants, variables, and functions.*/
intPtr = Mode(numbersPointer, mode, SIZE); //Call mode.
return 0;
}

Variable size array from table

I am new to c++ and I would appreciate if someone could help solving following problem.
When I want to create an array (Arr) with variable size (S), I do in the following way:
const int S=10;
int Arr[S];
However, in the code I am trying to write, I need to choose S from a Table. Let say I have following table:
int Table[3]={11, 21, 31};
and I choose S from the table and define Arr
const int S=Table[0];
int Arr[S];
I cannot compile this code because I get an error that S must have a constant have constant value.
I would appreciate any help/hint.
To fix the problem, you need to declare Table constexpr:
void foo() {
const int S=10;
int Arr[S];
constexpr int Table[3]={11, 21, 31};
constexpr int S2=Table[0];
int Arr2[S2];
}
Explanation: by declaring Table constexpr, you let compiler know that it knows it contents at compile time. Now it can be used whenver literal constants can be used, including array sizes. I'have shown the use of intermediate constexpr variable to illustrate this effect better, but you could use Table[0] as Arr2 size directly.
NB. constexpr is a keyword introduced in C++11, but I assume, it is safe to assume this dialect by default in 2016.

Declaring arrays with const variables

I am trying to create a multidimensional array, however when I pass a const int value I can't compile. Error is "expression must have a constant value" for each dimension.
class Matrix {
public:
Matrix(int rowCount, int columnCount, int scalarInput) {
const int row_C = rowCount;
const int colum_C = columnCount;
const int scalar_C = scalarInput;
matrixCalculation(row_C, colum_C, scalar_C);
}
void matrixCalculation(const int i, const int j, const int s) {
int matrixArray[i][j]; // error here, i and j: "expression must have a constant value"
}
};
Thanks
Array dimensions must be compile-time constant, and const doesn't mean that.
A const object cannot change its value after initialisation, but its initialiser may be determined at runtime (e.g. const int x = rand()) so, in general, these objects are not valid candidates for array dimensions.
Introducing... constexpr.
If you plonk the keyword constexpr in front of the dimensions, you will be off to a good start. Your compiler will prevent you from breaking the contract of constexpr, and will consequently enable you to use your shiny new constexpr object as an array dimension.
Alas, in this example, you are breaking that contract already, since the inputs are non-constant. Tough cookies.
Use a vector instead.

creating reference to a constant variable in C++

compiler says invalid initialization at line 3
I guess creating reference to i, it is telling the compiler that someone wants to change i, I guess this thing came with newer versions of the compilers because i have found this code in most of the books.
int main(){
const int &i=10;
int &j=1;
cout<<j;
return 0;
}
This:
int &j=1;
Is not valid, because you're creating a non-const reference (which would allow you to modify the referent) from a constant value (which cannot be modified, for obvious reasons).
Do this instead:
const int &j=1;
Also, the line that declares i makes no sense. Just delete it.
Besides missing an int in const &i=10; the issue with the next line is that you are creating a reference that is not const (i.e. which allows what it refers to to be changed) and the number 1 is a constant. You'd encounter the same problem with the following code:
const int i = 1;
int &ri = i;
It should be obvious why.