ruutis
ruutis

Reputation: 33

Says it cannot be used as constant

Visual studio 2019

const int inputs = 1, layers = 2, layerN = 3, output = 1;
const int how = inputs * layerN + pow(layerN,layers) + output * layerN;
float w[how];

it says on w[how] that it must be "const" expression(but is is??)

I cannot run the program with this error.

hielp.

Upvotes: 0

Views: 3419

Answers (6)

Andreas Wenzel
Andreas Wenzel

Reputation: 25396

Variable-length arrays (VLAs) are an optional feature of C. They do not exist at all in standard C++. Visual Studio 2019 does not support them at all (neither in C nor C++ mode). However, some other compilers do support VLAs in both C and C++ mode. In the case of C++, these are extensions to the C++ language that are designed to behave the same way as in the language C.

In cases in which VLAs are not supported by the compiler, the expression how must be known at compile-time. The reason why the compiler cannot determine the value of how at compile-time is because the expression contains a function call to pow(). Replacing the expression pow( layerN, layers ) with 3*3 (which can be evaluated at compile-time) will make your code work.

In C++, functions declared as constexpr are guaranteed to be evaluated at compile-time. However, the C++ standard library function pow is not declared as constexpr.

Even in cases in which VLAs are available, using them in C++ is generally not recommended. It is recommended to for example use std::vector instead, as that makes the program more flexible and also portable.

Upvotes: 1

eerorika
eerorika

Reputation: 238461

it says on w[how] that it must be "const" expression(but is is??)

It probably doesn't say that (in future, avoid paraphrasing error messages). I assume that it actually says that it must be a constant expression. The distinction may seem subtle, but is significant.

"Constant expression" is a specific term defined by the C++ language. There are many rules that specify whether an expression is constant, but a concise way to describe it is: Expression whose value is determined at translation time.

As confusing as it may be, an id-expression that names a const variable is not necessarily a constant expression. Constness of a type by itself merely implies that the variable is constant at runtime. And in this case, how specifically is not a constant expression.

The reason why how is not a constant expression is because its initialiser inputs * layerN + pow(layerN,layers) + output * layerN is not a constant expression. And that is because it contains a call to a non-constexpr function pow:

Here is a simple implementation of a constexpr pow function for int:

constexpr int
constant_pow(int base, int exp)
{

    return exp ? (base * constant_pow(base, exp-1))
               : 1;
}

Upvotes: 2

Guillaume Racicot
Guillaume Racicot

Reputation: 41840

The how variable is indeed const, but is not a constant expression. Such constant expressions are values and functions that have a known value and result at compile time, something known by the compiler before the program runs.

You can annotate your code to tell the compiler which variable should have a known value at compile time. This is what the constexpr keyword is for.

However, the pow function is not marked as constexpr so it's only useable at runtime and not also at compile time. You must implement your own function there:

constexpr auto power(int value, int exponent) -> int {
    for (int i = 0 ; i < exponent ; i++) {
        value *= value;
    }

    return value;
}

constexpr int inputs = 1, layers = 2, layerN = 3, output = 1;
constexpr int how = inputs * layerN + power(layerN,layers) + output * layerN;

Then it will be useable in a array size:

float w[how];

Live example

Also note that with this power function we created, we can revert back to const and the compiler will still accept it:

const int how = inputs * layerN + power(layerN, layers) + output * layerN;
float w[how];

The difference is that constexpr enforce compile time knowability, and const does not and you get the error later.

Upvotes: 2

Louen
Louen

Reputation: 3677

It doesn't word with const. The const keyword denotes a read-only variable but not necessary a compile-time constant, is necessary to specify the size of your array.

In other words the only thing const guarantees is that the value of the variable will not change, but not necessarily that it is known before the program executes. To declare an array, the compiler needs to know the size when it compiles.

However C++ 11 introduced the constexpr keyword for this very purpose. constexpr tells the compiler that the value of the variable can be known at compile time.

This code uses constexpr.

constexpr int inputs = 1, layers = 2, layerN = 3, output = 1;
constexpr int how = inputs * layerN + pow(layerN,layers) + output * layerN;
float w[how];

See it live here

This code will work provided that the pow function is declared as a constexpr function (a function declared as constexpr guarantees that it can compute its value at compile-time provided that its arguments are themselves known).

This seems to be the case in the GCC version I linked above but it is not guaranteed to work everywhere. If you want portable code, you can define your own version of the power function which will be constexpr.

EDIT : added detail about potentially non-constexpr pow

Upvotes: -1

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 123460

Perhaps it is more clear if you consider this example:

int x; 
std::cin >> x;
const int y = x;
float w[y];   // error

y is const, ie during runtime its value cannot possibly change. However to allocate memory for an array the compiler needs to know the size. Making y a constant alone is not sufficient to achieve that. In your case it is not reading user input, but the call to pow that prevents the compiler from knowing the value.

PS: You might want to read about constexpr which is a much stronger guarantee than const. Unfortunately there is no constexpr version of pow.

Upvotes: 4

Remy Lebeau
Remy Lebeau

Reputation: 598329

how is not a constant expression. Its value is not known to the compiler at compile-time, it is calculated dynamically at runtime because of the function call to pow(). As such, it cannot be used to declare a fixed length array. You will have to use new[] or a std::vector instead:

float *w = new float[how];
...
delete[] w;
#include <vector>
std::vector<float> w(how);

Upvotes: 5

Related Questions