0

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.

scohe001
  • 15,110
  • 2
  • 31
  • 51
ruutis
  • 3
  • 2
  • I believe you're looking for `constexpr`: [const vs constexpr on variables](https://stackoverflow.com/q/13346879/2602718) – scohe001 Feb 18 '20 at 17:40
  • @scohe001 `constexpr` will not help here. If the initializer was a constant expression, the `const int` variable would be usable as if it were declared `constexpr` anyway. – walnut Feb 18 '20 at 17:54
  • @walnut: that would spot the error to the place where it is not `constexpr` though. – Jarod42 Feb 18 '20 at 18:05
  • Unfortunately for you, `pow`is not `constexpr` as you might expect. – Jarod42 Feb 18 '20 at 18:14

6 Answers6

5

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);
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
4

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.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • Notice that OP doesn't really use runtime value. it is just that `pow` is not (yet) `constexpr` as we might expect. (gcc has even add `constexpr` to some functions like this one (which is so no standard conformant)). – Jarod42 Feb 18 '20 at 18:18
2

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.

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
  • Experiencing the same thing in Visual Studio which does not provide an option for me to create a C project separately from C++ and whenever I try to use the integer parameter of a method to create an array then I get that error – Son of Man Jun 11 '23 at 05:53
  • @PassionateSE: As far as I know, whether a source file is compiled in C or C++ mode is determine by the extension of the file (i.e. `.c` or `.cpp`). However, as stated in my answer, even for C files, the Visual Studio compiler does not support VLAs, so changing the language to C will not help. I believe that the latest version of Visual Studio still does not support VLAs, as I have not heard anything to the contrary. However, even if cases in which VLAs are supported, using VLAs in C++ is generally not recommended. It is recommended to for example use `std::vector` instead. – Andreas Wenzel Jun 11 '23 at 10:00
  • Did Microsoft assume that C++ is an extension of C hence not letting us create projects using the C language. It's just C++, this could be true because Cpp source files accept programmers to use C Syntax and code in those files – Son of Man Jun 11 '23 at 10:09
  • @PassionateSE: A Visual Studio C++ project allows you to include both `.c` and `.cpp` files. It even allows you to mix these two types of files in the same project. Therefore, I do not see any issue in that respect. – Andreas Wenzel Jun 11 '23 at 10:21
  • @PassionateSE: The original version of C++ is based on the ANSI C standard, which was published in the year 1989. C++ was designed in such a way that most ANSI C code also runs in a C++ compiler. However, because C++ has more type-safety than C, certain code will not work. For example, in C, you can write `int c = malloc( 100 * sizeof(int) );`, but this will not work in C++. In C++, you require an explicit type cast for type-safety. Since then, both languages have evolved (also called ANSI C). Since 1989, both langauges have evolved somewhat independantly, but are still mostly compatible. – Andreas Wenzel Jun 11 '23 at 10:28
  • issue is C++ won't le me do _int size =9; char name[size];_ – Son of Man Jun 11 '23 at 10:29
  • 1
    @PassionateSE: In C++ (but not in C), you can do `const int size = 9; char name[size];`. Once the new ISO C standard (C23) is released, `constexpr int size = 9; char name[size];` will work in both C and C++. – Andreas Wenzel Jun 11 '23 at 10:31
  • Thanks for the tip. I was switching between C IDEs to get that line to compile. – Son of Man Jun 11 '23 at 10:39
  • @PassionateSE: If you want it to work on a C (not C++) compiler that does not yet support C23, then the most common solution is to write `#define SIZE 9` at the start of the file and to use `char name[SIZE];`. However, it may be better to use `enum { SIZE = 9 };` instead of `#define SIZE 9`, as this will allow you to limit the [scope](https://en.cppreference.com/w/c/language/scope) of `SIZE` to a single code block. However, as previously stated, as soon as C23 is supported, it would probably be best to use `constexpr int SIZE = 9;`. – Andreas Wenzel Jun 11 '23 at 13:34
  • Yes thanks for that, I can't believe I never thought of that. Am gonna declare the size as a global at the top of the file. – Son of Man Jun 11 '23 at 13:36
2

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;
}
eerorika
  • 232,697
  • 12
  • 197
  • 326
2

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.

Guillaume Racicot
  • 39,621
  • 9
  • 77
  • 141
-1

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

Louen
  • 3,617
  • 1
  • 29
  • 49
  • 3
    Do note that this code is not portable. `pow` is not marked `constexpr`: https://en.cppreference.com/w/cpp/numeric/math/pow – NathanOliver Feb 18 '20 at 17:47
  • Thanks for the insights on non-constexpr `pow` – Louen Feb 18 '20 at 17:56
  • 1
    `constexpr` does not change anything. `const` variables of integral type can be used as if they were declared `constexpr` if they are initialized by a constant expression. Using `constexpr` instead of `const` does not change whether the initializer is a constant expression or not. – walnut Feb 18 '20 at 17:59
  • Also, the `constexpr` `pow` issue is not only non-portable in the sense that it is implementation-defined. It is actually explicitly prohibited and GCC is non-conforming to the standard. See [\[constexpr.functions\]](https://eel.is/c++draft/constexpr.functions#1) and [LWG defect report 2013](https://cplusplus.github.io/LWG/lwg-defects.html#2013). – walnut Feb 18 '20 at 18:10