1
votes
constexpr int hello(int j) {
    return j * 12;
}

constexpr int bye(int j = 6) {
    return j * 12;
}

int main() {
    int i = 6;
    constexpr int a1 = hello(i); //error
    constexpr int a2 = hello(6); //ok
    constexpr int a3 = hello(int(6)); //ok
    constexpr int a4 = bye(); //ok
    constexpr int a5 = bye(i); //error
    constexpr int a6 = bye(6); //ok
    return 0;
}

What's difference between hellow(i) and hello(6)? I think one is int j = i; and j is not a constexpr, while the other is int j = 6 and j is still not a constexpr, both j are int type.
int * literal != constexpr, so the return type is not a constexpr.

I got the above conclusion from an example in the book:
int staff_size = 27; //staff_size is not a const expression

Although staff_size is initialized from a literal, it is not a constant expression because it is a plain int, not a const int.

Moreover, I notice that hello(int(6)) works fine too, what's the "thing" here?

Additionally, bye() works while hello(i) does not, both parameter are initialized inside the function, only one with default value, what's the point here?

Very confused, hope someone could explain :D

PS: have no idea to figure out a better title, sorry for that

2
constexpr-ness propagates. 6 is constant, i is not. It isn't enough you didn't modify it, you need to declare it.Passer By
An int literal IS a constant expression. And int(6) has the same semantics as the int literal 6 (both an rvalue).DeiDei
@PasserBy if it's really "propagates". Then why this doesnt work? constexpr int j1 = 6; int q = j1; constexpr int j2 = q; It should be fine since j1's constexpr-ness propagates to q, then q should be able to intialized another constexpr.Rick
That's loosely speaking. I meant constexpr functions have constexpr value iff it's parameters are constexpr. q is initialized by a constant doesn't mean q` is a constantPasser By

2 Answers

1
votes

The thing to note here is that the compiler "validates" the code, it doesn't "read" it.

The compiler expects all parts of a constexpr to be a known valid constant at compile time. So although you and I know, from reading the code, that the value of i never changes, the compiler doesn't "know" it unless you declare i to be a constant. As far as it is concerned you could have executed other code somewhere to change the value of i.

In all the cases where the function is called without the i, the compiler knows for a fact, without a doubt, that the value of j is a constant integer with a value of 6, (note: int(6) is the same as just 6).

3
votes

The difference between hello(6) and hello(i) is that the 6 in hello(6) is a constexpr function parameter, while the i in the hello(i) is a regular int parameter.

If you declare i to be constexpr int i = 6;, then hello(i) will compile and execute.

In hello(int(6)), you're saying cast 6, an integer literal, into an int. This is a redundant operation. hello(int(6)) and hello(6) will have similar, if not identical behavior.

bye() works since the function parameter uses the default parameter (the j = 6 in constexpr int bye(int j = 6);). The default initialized parameter is known at compile time, thus, is a constexpr by definition