I wrote a simple test program using CGAL, and running into the following issue:
Point is defined above as
typedef K::Point_d Point;
but I don't think this is relevant.
When I attempt to compile the program as follows:
const int size = 10;
Point P[size];
g++ does so without issue.
If instead I attempt to compile:
const int size = stoi("10");
Point P[size]
I get the following error
error: variable length array of non-POD element type 'Point' (aka 'Point_d<Cartesian_d<double,
CGAL::Linear_algebraCd<double, std::__1::allocator<double> > > >')
Why is size considered a variable instead of a const when retrieved from a string?
C++ defines specific things to be constant expressions that are defined to be known at compile time - see constant_expression.
In general functions that are not defined as constexpr are not, regardless of what you pass them. You could try and force it as such:
#include<string>
constexpr int x = std::stoi("10");
int main() {
return 0;
}
but you will find this still leads to an error:
error: call to non-constexpr function 'int std::stoi(const string&, std::size_t*, int)'
so, you are out of luck as stoi is not a constant expression. If you really insist you could override this using your own implementation for example that in How do I convert a C string to a int at compile time?.
stoi is not evaluated at compile time. That means the compiler does not know how big the array should be.
if you want to do something like that you have to use a constexpr function (constexpr function). These can be evaluated at compile time, then it works.
The compiler doesn't understand the semantics of the stoi function. All it sees is you calling a function that returns an integer (whether that function can be inlined and optimized away is a seperate issue from the semantics).
To the compiler there is very little semantic difference between
const int size = stoi("10");
and
const int size = getchar();
As other answers mentioned constexpr being the exception. I just thought I'd illustrate the issue.
The first const int size = 10; is a compile time const expression and it can be computed during compilation,
but const int size = stoi("10") is not a compile time const expression hence it fails to compile.
std::stoi is not a constexpr function to evaluated on compile time.
If you want to have this functionality you may need to create a constexpr function to evaluate on compile time.
constexpr bool is_digit(char c) {
return c <= '9' && c >= '0';
}
constexpr int stoi_impl(const char* str, int value = 0) {
return *str ?
is_digit(*str) ?
stoi_impl(str + 1, (*str - '0') + value * 10)
: throw "compile-time-error: not a digit"
: value;
}
constexpr int to_int(const char* str) {
return stoi_impl(str);
}
int main() {
constexpr int size = to_int("10");
int arr[size];
}
This will compile; [copied from here]
In the first code sample
const int size = 10;
Point P[size];
the particular value of size can be used already at compile time, since it is known (you've specified it). Therefore the compiler may replace all its uses with particular value, w/o actually creating a variable.
In the second sample
const int size = stoi("10");
Point P[size]
the compiler cannot know the value, since it is deduced by the stoi function at runtime. Therefore it cannot substitute the size of the array (which must be known beforehand to determine now much memory to allocate), and you get the error.
In C++11 there is constexpr idiom, which allows some functions, declared as constexpr, be evaluated at compile time. But in your case stoi isn't constexpr function, so you cannot achieve what you want using this particular function. You can implement your own constexpr stoi, but I don't see much sence in it, since your code in this case would contain somethins like this: my_constexpr_stoi("10"), i.e. the argument is always manually written and always known beforehand. Why don't write just 10?..
To expand on kabanus’ answer, the language standard says that an array bound in C++11 must be something called an integral constant expression. C++17 relaxes this slightly and allows a few more things, but that’s not important right now.
This page at cppreference lists all the things you are not allowed to do inside a constant expression. It basically quotes the language standard.
The relevant section that allows your first example is 8a. You are not allowed to use a variable, unless it’s a const variable initialized to a constant expression. So using the name of a const variable of integral type that is initialized to a constant expression is legal, as in your first example. Numeric constants are constant expressions, so size is a const variable initialized to a constant expression, which is A-OK.
However, due to point 2, function calls are only constant expressions if they are both declared constexpr and already defined. So, for a standard library function to be usable in an array expression in your code, it would need to be declared constexpr and also defined in the header file.
The standard does not say that stoi() qualifies, although I don’t think anything in it directly forbids some implementation from providing that as an extension.
Related
I ran across this seemingly odd behavior. A const at top level can be used for array size declarations, but not when the const is in a class.
Here's a compiler explorer demo for MSVC, CLANG and GCC all producing an error:
expression did not evaluate to a constant
It's not really a constant if it's not const at the top level?
There's some argument to be made because top level constants can often be stored in read-only memory, while constants that are not at top level cannot. But is this behavior correct?
struct A {
const int i{ 3 };
};
int main()
{
const int ii{ 3 };
A a;
int j[a.i]{}; // C2131: expression did not evaluate to a constant
int k[ii]{};
}
Generally, you can use (meaning perform an lvalue-to-rvalue conversion on) objects with lifetime starting outside a constant expression only if they are variables marked constexpr or their subobjects (plus some other special cases, that I don't think are important here, see [expr.const]/4 for details).
That you can use a const int variable at all in a constant expression is already a very specific exception. Essentially const-qualified integral and enumeration type variables are also usable in constant expressions if you could have added constexpr to them (meaning that their initializer expression is a constant expression).
This exception is there I guess purely for historical reasons, since it had been allowed before constexpr was introduced in C++11.
Note that all of this talks about variables and their subobjects. Non-static data members are specifically not variables and the exception doesn't apply to them. With constexpr this is more obvious by not allowing it on the declaration of a non-static data member in the first place.
The historical rule was never extended to encompass other types that could be marked constexpr, so e.g. const A a; will not help although that would actually cause a to be storable in read-only memory the same way a const int would.
If an object is none of the cases mentioned above, then an lvalue-to-rvalue conversion on it in a constant expression is not allowed, since it is assumed that the value of the object is not determined at compile-time.
Now, in theory the compiler could still do some constant folding and determine that even other objects' values are definitively known at compile-time. But I think the intention is that whether or not an expression is a constant expression should be (reasonably) well-defined independently of the implementation and so shouldn't rely on how much analysis the compiler can do.
For example
A a;
A b(a);
is also guaranteed to result in b.i == 3. How far do you want to require a compiler to go back or keep track of evaluations? You would need to make some definitive specification if you want to keep the behavior consistent between compilers. But there is already a simple method to indicate that you want the compiler to keep track of the values. You just have to add constexpr:
constexpr A a;
constexpr A b(a);
Now b.i can be used as array index (whether or not it is const and whether or not it is initialized).
With the current rules, any compiler only needs to evaluate the value of objects at compile-time when it sees a constexpr variable or a const integral/enumeration type variable. For all other variables it doesn't need to keep track of values or backtrack when it sees them used in a context which requires a constant expression.
The additional effect of constexpr implying const on the variable makes sure that its value will also never be changed in a valid program and so the compiler doesn't need worry about updating or invalidating the value after the initial computation either. And whether or not an expression is a constant expression is (mostly) implementation-dependent.
ii is a compile-time constant. Its value is known at compile-time, and cannot be changed at runtime. So, ii can be used for fixed array sizes at compile-time.
A::i is not a compile-time constant. It is a non-static instance member. Its value is not known until runtime. After an A object is constructed and its i member is initialized, the value of i cannot be changed because of the const, but the caller can initialize i with whatever value it wants, eg: A a{123};, and thus different A objects can have different i values. So, i cannot be used for fixed array sizes at compile-time. But, it can be used for dynamic array sizes at runtime, via new[], std::vector, etc.
TL;DR
Your assumption that const always implies compile time constant is incorrect. See examples at the end of this answer for more details on this.
Now the problem in using a.i as the size of an array is that in standard C++, the size of an array must be a compile time constant, but since i is a non-static data member, it requires an object to be used on. In other words, after construction of the class object nonstatic data member i gets initialized, which in turn means that a.i is not a constant expression, hence we get the mentioned error saying:
expression did not evaluate to a constant
To solve this, you can make i be a constexpr static data member, as shown below. This works because using a static data member doesn't require an object instance (and hence no this pointer).
struct A {
constexpr static int i{ 3 };
};
int main()
{
const int ii{ 3 };
A a;
int j[a.i]{}; //Correct now and works in all compilers
int k[ii]{};
}
I just don't get why a regular const works in some places but not others.
Perhaps you assuming that const implies compile time constant which is a wrong assumption. An example might help you understand this better:
int i = 10; //i is not a constant expression
const int size = i; //size is not a constant expression as the initializer is not a constant expression
//------vvvv------>error here as expected since size is not a constant expression
int arr[size]{};
On the other hand if you were to make i const as shown below, the program will work fine.
const int i = 10; //note the const added here so that now i is a constant expression
const int size = i; //size is a constant expression as the initializer is a constant expression
//------vvvv------>NO ERROR HERE as expected since size is a constant expression
int arr[size]{};
What I'm trying to accomplish is this:
inline const int size() { return 256; }
int main()
{
int arr[size()];
return 0;
}
But Visual Studio gives me an error when initializing arr[size()]:
expression must have a constant value
Is there a way to accomplish what I want without using global variables, Macros, std::vector or creating arr[ ] on heap?
Drop the inline and const and add constexpr specifier instead, to solve the issue:
constexpr int size() { return 256; }
now you can use it as array size like:
int arr[size()];
In C++ (not C) length of arrays must be known at compile time. const qualifier only indicates that a value must not change during running time of a program.
By using constexpr you will specify that the output of the function is a known constant, even before the program execution.
Looks like error message is confusing you. The problem is you do not need a constant value as message says but constant expression:
Defines an expression that can be evaluated at compile time.
Such expressions can be used as non-type template arguments, array sizes, and in other contexts that require constant expressions, e.g.
and to achieve that you can add constexpr specifier:
The constexpr specifier declares that it is possible to evaluate the value of the function or variable at compile time. Such variables and functions can then be used where only compile time constant expressions are allowed (provided that appropriate function arguments are given).
to your function allowing compiler to evaluate it as constant expression
constexpr const int size() { return 256; }
Note: declaring return type by value as const does not really make any difference so you can simply remove that.
You can replace const with constexpr as others have pointed out, but I should add that your original code compiles fine using the G++ compiler because it supports variable-length arrays, unlike Microsoft's compiler.
From C++20, you can also make size an immediate function, i.e. a function that is guaranteed to be evaluated at compile time.
consteval int size() { return 256; }
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.
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);
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.
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.
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;
}
Variable-length arrays (VLAs) are an optional feature of C, not C++. Visual Studio 2019 does not support them at all (neither in C nor C++ mode). However, some other compilers support VLAs even in C++ mode. These are compiler-specific extensions, though, and not part of the official C++ standard.
In cases where 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.
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
The following code is meant to create sort of a trivial hash of a string up to 8 characters long:
#include <type_traits>
#include <cstdint>
#include <iostream>
template<std::size_t N, std::size_t n=N>
constexpr typename std::enable_if<N<=9 && n==0,
uint64_t>::type string_hash(const char (&)[N])
{
return 0;
}
template<std::size_t N, std::size_t n=N>
constexpr typename std::enable_if<N<=9 && n!=0,
uint64_t>::type string_hash(const char (&array)[N])
{
return string_hash<N,n-1>(array) | ((array[n-1]&0xffull)<<(8*(n-1)));
}
For normal string literals and constexpr NULL-terminated strings it does indeed work normally. But if I do something like this:
constexpr char s2[] = {1,2,3,4,5,6,7,8,9};
std::cout << string_hash(s2) << "\n";
, the output will be the same as for the string "\x1\x2\x3\x4\x5\x6\x7\x8". I've tried adding a static_assert(array[N-1]==0,"Failed"); in the definition of string_hash, but the compiler says that array[N-1] is not a constant-expression. I then tried declaring the parameter constexpr, but the compiler said a parameter can't be declared constexpr.
How can I then do this check?
Please keep in mind that although constexpr functions can be used at compile time, they don't need to be. You cannot add any static assertions on runtime parameters, because the static assertion would be impossible to evaluate when the parameters are not known at compile time.
What you can do is the same thing you can do for non-constexpr functions: throw something. This doesn't prevent your function from being called with invalid input, but does prevent silent wrong results. And when your function is used in a context requiring a constant expression, the compiler will correctly detect it as not returning a constant value.
The body of a constexpr function needs to be a single return statement in C++11, but you can still fit it in there:
return array[N-1] ? throw "bad!" : <your current return expression here>;
Do pick something better to throw though.
The reason why the compiler is complaining is because the array is unknown at the time when string_hash<N,n> function is being instantiated. static_cast is evaluated when instancing, and not when invoking (even if it is constexpr function).
Notice that there will be exactly one function created for each pair of <N,n> values. If you use two constexpr strings of same length, exactly same instance of string_hash will be used, but depending on the argument array[N-1] may give a different result.
I will continue to search for a precise answer to your question if it is needed. However, as a "quick fix", may I suggest changing the hash function so that it always include the last character in the computation, be it 0 or not?
Update:
after doing some digging, I learned that some kind of constexpr_assert is what you probably want in your case and it is currently missing from the standard. Hopefully they will add it in the future. You may want to check:
g++ doesn't compile constexpr function with assert in it
Alternative to asserts for constexpr functions
http://ericniebler.com/2014/09/27/assert-and-constexpr-in-cxx11
I'm just wondering whether sentences like const int N=10 will be executed at compilation time. The reason I'm asking is because that the following code will work.
int main()
{
const int N=10;
int a[N]={};
return 0;
}
But this one wouldn't.
int main()
{
int N=10;
int a[N]={};
return 0;
}
The compiler must generate code "as if" the expression was evaluated at
compile time, but the const itself isn't sufficient for this. In
order to be used as the dimension of an array, for example, expression
N must be a "constant integral expression". A const int is
a constant integral expresion only if it is initialized with a constant
integral expression, and the initialization is visible to the compiler.
(Something like extern int const N;, for example, can't be used in
a constant integral expression.)
To be a constant integral expression, however, the variable must be
const; in your second example, the behavior of the compiler and the
resulting program must be "as if" the expression were only evaluated at
runtime (which means that it cannot be used as the dimension of an
array). In practice, at least with optimization, the compiler likely
would evaluate N at compile time, but it still has to pretend it
can't, and refuse to compile the code.
The compiler will probably evaluate both of the examples you provided at compile time, since even though the int N = 10; isn't const, you're not changing it anywhere and you're only assigning a constant value to it, which means the compiler can optimize this.
I recommend you take a look at the constexpr keyword introduced in C++11, which is exactly about being able to evaluate things at compile time.
Compilers will resolve const variables to literals at compile time (and also const expressions, see constant folding). The reason that the first method works is that compiler knows how much space to allocate (10*sizeof(int)) to a in the first method. In the second method the value of N is not known at compile time, and as such there is no way for the compiler to know how much space to allocate for a. Hope that helps.
This sort of thing is an implementation detail that technically is up to the compiler to choose. It could be different on different platforms.
In practice, with the most common compilers:
const int sometimes is and sometimes isn't baked at compile time. For example, the compiler clearly can't hardcode the value of a below into the object file:
int foo( int x )
{
const int a = x+ 1;
return a * 2;
}
In that function, const means it is only constant within the scope of foo(), but it is still a local stack variable.
On the other hand, const int x = 5 seems to be a literal that is usually resolved at compile time by GCC and MSVC (except sometimes they don't turn it into a literal for reasons unclear). I've seen some other compilers that won't turn it into a literal, and always put const int on the stack like an ordinary local variable.
const static int is different, because its scope is static, which means it outlives the function it is declared in, which means it will never change over the life of the program. Every compiler I've ever worked with has turned const static primitives into compile-time literals.
Objects with constructors, however, will still need to be initialized at runtime; so
class Foo {
Foo() : { CallGlobalFunction(); }
};
const static Foo g_whatever;
cannot be optimized into a literal by the compiler.