I am finding it a bit hard to understand why the following results in a compile time calculation. I have read this, this, this and a lot more questions on stackoverflow that tell me the following code( at least to my understanding) should not be computed at compile time because of the while loop (The code is just an example to illustrate the question):
template< unsigned N >
constexpr unsigned isStringNice(const char (&arr)[N], unsigned pos = 0)
{
//we do not like the 'D' char :)
int currPos = 0;
while(currPos < N){
if(arr [currPos] == 'D'){
throw 1;
}
currPos ++;
}
return 1;
}
constexpr unsigned isIdxValid( unsigned idx, unsigned len){
return idx >= len? throw 1 : idx;
}
template< unsigned N >
constexpr char nth_char(const char (&arr)[N], unsigned pos){
return isStringNice(arr),isIdxValid(pos, N),arr[pos];
}
int main(){
constexpr char b = nth_char("ABC", 2);
return b;
}
this outputs with no flag the following assembly code (gcc 8.2 , thank you Godbolt) main:
push rbp
mov rbp, rsp
mov BYTE PTR [rbp-1], 67
mov eax, 67
pop rbp
ret
and with -O3
main:
mov eax, 67
ret
Notice as there is no jump in there, no branch on the while condition, nothing. I had the impression that for-loops and while loops were not possible to be evaluated at compile time. However, the compiler (gcc 8.2) evaluates the result at compile time.
My only thought is this happens because of loop unrolling, so i tried using -fno-unroll-loops
, but this results in the same assembly code.On the other hand from my experience, this flag is more like a compiler suggestion than a guarantee and gcc might still unroll the loop even though the flag is set.
Short version of my question: How come my while loop in a constexpr function is evaluated at compile time?
In C++14, constexpr
function requirements were relaxed.
Previously, in C++11, constexpr functions could only contain typedef
s, static_assert
s and using
s, but only a single return statement.
In C++14, it became possible to use loops in constexpr
function bodies.
Because b
was declared as constexpr char
, it must be evaluated at compile time. The compiler then optimised out the isStringNice
function, as it is not used at run time.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With