const int x = readInput();
cannot be constexpr. Consider constexpr as a compile time assertion that a given symbol is available at compile time. If you didn't have the constexpr keyword then you would have have to inspect the definition to determine that every subexpression is constexpr.Yes, that's what I meant with "the compiler can do it".
Heavy type inference, overloading, and inheritance are a completely different beast and they make the code a lot more opaque.
const int x = const foo(bar(y));
?Unfortunately, there is a big political war ongoing, so instead C++ keeps collecting const.... keywords.
They could have just used "pure" like in D, but this is C++, so that would be too sane and obvious.
It's also why they reuse keywords like `using`.
Edit, typo: I meant "You don't want every const-able method to be const."
You don't even need 'const' for this. Under the as-if rule, subsets of the program could always already be evaluated at compile time and have the result substituted in the program. Compilers already did that when they had the definition handy. Like just do int x = f(5); and then define int f(int x) { return x * 2; } and you'll get int x = 10; in any compiler without any keywords whatsoever. The constexpr keyword just cluttered the code for no good reason.
My code is C style and unrealistically simple, yet the compiler can't even constant-fold that.
If you've looked at the output of real compilers, you'd know that it's unrealistic for a language to let you to use the result of an arbitrary function call where you'd normally use a constant.
For one thing, constexpr guarantees that errors will produce compilation failures. (At least it guarantees that when used in certain ways; unfortunately C++ overcomplicates things.) In a version of C that doesn't have an explicit constexpr keyword but does allow the compiler to treat arbitrary variables as constants, you could perhaps approximate this by using a value in a context that forces it to be a constant expression… e.g. `const int x = foo(); _Static_assert(x == x);`. But that's a hack. Much better to have an explicit way to say "please evaluate this at compile time".
Also, suppose the user doesn't use an expression in a way that forces it to be evaluated at compile time, but you still want to allow the compiler to do constant evaluation for the sake of faster runtime performance or smaller code size. In this example, should fib(35) be evaluated at compile time or runtime?
unsigned int fib(int n) {
return n <= 1 ? 1u : fib(n - 1) + fib(n - 2);
}
int main() {
fib(26);
}
It depends on the user's intent. In this case, evaluating fib(35) takes less than a millisecond at runtime on my computer, but evaluating it as constexpr with clang requires about a full second. (After all, naive fib performs an exponential number of recursive calls.) Sounds like it's probably a job for runtime… unless the user really values runtime performance or code size more than compile times (maybe they're targeting a really slow CPU), in which case they might prefer it to be done at compile time. Best to give them a choice.Making things worse, the compiler has no real way of knowing how long something will take to constant-evaluate other than trying and seeing. It can give up after a timeout, but if the timeout isn't very tiny, it risks wasting a lot of time on aborted constant evaluation attempts. Therefore, while optimizers already try to perform opportunistic constant folding, they have to be very conservative with it. This problem doesn't occur if the compiler knows that something should be constant-evaluated because the user has marked it as such.
In that example, at compile time. If you write fib(35) you deserve to have to wait for the compiler to do it at compile time instead of at run time. (I'm not saying this to be funny. I'm really trying to make a point. You really do need a realistic example to motivate your side of the argument. If they're hard to come up with, that's kind of my point.) And honestly if I wrote that I would fully expect my compiler's optimizer to already waste that time constant-folding anyway; if I was concerned about its compile time I wouldn't write that even without constexpr.
> Best to give them a choice.
A need for that choice (assuming it's even necessary here, which is debatable, see above) doesn't mean you need a new keyword, especially not for functions. It could've been an attribute, and whatever it is, it only really makes sense on variables, not functions. And whatever it is, turning it into an exclusion instead of an inclusion would probably make sense here, seeing as how so much of the standard library has constexpr in front of it.
Same reason why fib(2) might be.
> What if it's fib(1500)?
Are you familiar with exponential growth? This would take longer than the heat death of the universe, whether you evaluate it at compile time or run time...