Honestly, it seems to me like the committee is constantly chasing the easy bits but is failing to address the bigger issues in the language and, more importantly, the standard library.
On Windows, you can do this today:
auto response {co_await httpClient.GetStringAsync(uri)};
The more you add to the standard, the narrower the platform support gets. Should we also force C++ to only be able to target 64-bit hosts? How about requiring hardware vector support? See what I’m getting at?
If you just want to make an async nw call, there are lots of things you can do that in already. If you want to write an async nw driver or library, then maybe you should use C++.
"sanity" might refer to default behaviors. If it does, there's not a lot you can do there either. You can't go changing fundamentals of how the language works, because backwards compatibility is paramount. There would be riots if a new standard broke significant chunks of legacy code - even for the better.
I don't understand why it is so complex in C++.
inline int foo(int x) { return x + 42; }
int arr[foo(1)];
I think it would qualify as spooky action-at-a-distance if modifying foo causes arr to be malformed. And if they are in different libraries it restricts the ways the original function can be changed, making backwards compatibility slightly harder.The Rust const fn foo which gives back x + 42 for any x, is genuinely assured to be executed at compile time when given a constant parameter. If we modify the definition of foo so that it's not constant the compiler rejects our code.
But C++ constexpr just says "Oh, this might be constant, or it might not, and, if it isn't don't worry about that, any constant uses will now magically fail to compile", exactly the spooky action at a distance you didn't want.
When originally conceived it served more or less the purpose you imagine, but of course people wanted to "generalize" it to cover cases which actually aren't constant and so we got to where we are today.
// C++
constexpr Foo bar() { /* ... */ }
constexpr Foo CONSTANT = bar(); // Guaranteed to be evaluated at compile time
constinit Foo VARIABLE = bar(); // Guaranteed to be evaluated at compile time
// Rust
const fn bar() -> Foo { /* ... */ }
const CONSTANT: Foo = bar(); // Guaranteed to be evaluated at compile time
static VARIABLE: Foo = bar(); // May or may not be evaluated at compile time
So Rust is actually less powerful than C++ when it comes to non-constant globals because AFAIK it doesn't have any equivalent to constinit. static VARIABLE: Foo = bar(); // May or may not be evaluated at compile time
Under what circumstances would this not be evaluated at compile time? As far as I know the initializer must be const.Unlike C++, Rust does not have pre-main (or pre-_start) runtime initializers, unless you use something like the ctor crate. And the contents of that static must be already initialized, otherwise reading it (especially via FFI) would produce unknown values.
To evaluate something at runtime you'd have to use a LazyCell (and LazyCell::new() is const), but the LazyCell's construction itself will still be evaluated at compile time.
The VARIABLE in Rust is an immutable static variable, similar to the thing you named CONSTANT in C++ and likewise it is constant evaluted so it happens at compile time, there is no "may or may not" here because the value is getting baked into the executable.
If we want to promise only that our mutable variable is constant initialized, like the C++ VARIABLE, in Rust we write that as:
let mut actually_varies = const { bar() }; // Guaranteed to be evaluated at compile time
And finally, yes if we write only: let mut just_normal = bar(); // This may or may not be evaluated at compile time
So, I count more possibilities in the Rust, and IMNSHO their naming is clearer.Especially now that it is a good practice to define c++ functions like
auto f(auto &&x) -> decltype(1+x)
?
Compilers are always allowed to CTFE than what the C++ standard specifies, many do. The standard is just moving the lower bar for what all compilers must now evaluate at compile time, and what c++ programmer may expect from all compilers.
Since C++11, they have been massively extending the subset of the language that can be evaluated at compile time. C++14 allowed compiletime evaluation of loops and conditionals, along with local variables. C++20 allowed CTFE functions to do memory allocation (as long as it was also freed) along with calling object constructors/deconstructors.
The main new thing in C++26 is the ability to do CTFE placement new, which is something I remember missing the last time I tried to do fancy C++ stuff. Along with marking large chunks of the standard library as constexpr.
Here's the thing - that cannot be fixed. Consider the x87 FPU. It does all computations to 80 bits, regardless of how you set the flags for it. The only way to get it to round to double/float is to write the value out to memory, then read it back in.
Java tried this fix. The result was a catastrophe, because it was terribly slow. They backed out of it.
The problem has since faded away as the X86_64 has XMM registers for float/double math.
C still allows float to be done in double precision.
D evaluates CTFE in the precision specified by the code.
More to the point, constexpr does supply something D doesn't do. Whether D runs a calculation at compile time or run time is 100% up to the programmer. The trigger is a Constant-Expression in the grammar, a keyword is not required.
BTW, D's ImportC C compiler does the same thing - a constant expression in the grammar is always evaluted at compile time! (Whereas other C compilers just issue an error.)
int sum(int a, int b) { return a + b; }
_Static_assert(sum(1,2) == 3, "message"); // works in ImportC
_Static_assert(sum(1,2) == 3, "message"); // gcc error: expression in static assertion is not constant
I think there's something in the psychology of developers that appreciates the byzantine web of stuff which looks like it will work but doesn't.
An alternative design would be "global initialisations are evaluated at compile time where possible, like everything else, and you don't need to annotate anything to get that". Which would require exactly the same compiler work as constexpr but wouldn't leave that word scattered around codebases in similar fashion to register.
https://www.godbolt.org/z/Kja5jrWo5
>I don't understand why it is so complex in C++
Because C++ is a completely overengineered boondoggle of a language where every little change destabilizes the Jenga tower that C++ had built on top of C even more ;)
int sum(int a, int b) { return a + b; }
_Static_assert(sum(1,2) == 3, "message");
gcc -c -O x.c
x.c:2:17: error: expression in static assertion is not constant
_Static_assert(sum(1,2) == 3, "message");
If the author then changes the internals of the function so that it can no longer be constexpr, then they've broken that promise. If constexpr was implicit, then a client could come to depend on it being constexpr and then a change to the internals could break the client code.
Disclaimer: this is not a normative statement.
nokeya•2mo ago
nly•2mo ago
dnf install gcc-toolset-X
pjmlp•2mo ago
So expect at very least 2026 + 5 => 2031 for that command to provide a complete C++26 development experience.
gpderetta•2mo ago
mkoubaa•1mo ago
pjmlp•1mo ago
int_19h•1mo ago
And constexpr in stdlib is much more likely to get quick adoption across all implementations than something like modules.
pjmlp•1mo ago
int_19h•1mo ago
mkoubaa•1mo ago
pjmlp•1mo ago
ender341341•2mo ago
on the other hand constexpr changes tend to be picked up pretty quickly, and a lot of them tend to be things that the compiler/stl authors themselves are asking for.
pjmlp•1mo ago
Yes it might prevent lots of cool features, yet how good are they if it takes years to be implemented across compilers, or they turn out to be yet another export template.
Additionally it would help to reduce count from those 300+ people, not everyone is there for good reasons, some only want to have a "contributed to C++" on their background, and then they are gone.
ender341341•1mo ago
When c++11 was still c++0x they made a big song and dance about how they wouldn't do another export template boondoggle and wanted an implementation available for any features. Then they seemed to have completely forget about it when doing modules (which not that surprisingly is running into similar issues that export templates did).
WalterBright•1mo ago
phire•1mo ago
But C++ really wanted modules to be a more or less drop in replacement for #include (or at least a set of common use cases), which really pushed up the required level of complexity.
pjmlp•1mo ago
Note at WWDC 2024, the module improvements regarding build times, in what concerns C++, it is based on header maps as well. Apple is not even bothering with C++20 modules.
pjmlp•1mo ago
Many things D might have done it first, yet it is hardly acknowledged, or has any impact on adoption without a major backer.
I also keep telling WG14 should care about security, since Usenet days, fighting windmills.
WalterBright•1mo ago
pjmlp•1mo ago
Also some of those features predate D, having shown first in Ada, Common Lisp, Eiffel, as discussed in the past.
WalterBright•1mo ago
I've pointed out many times that thousands markers in D came from Ada. However, no other language did them until D did.
Yes, Lisp has compile time function execution. Where it remained until D did it with a compiled language.
C++'s implementation of ranges is still based on pointers (an iterator pair), rather than based on arrays as in D. The language loses semantic information because there is no particular thing that connects the iterator pair as being the limits on an array. Basing ranges on arrays enables crucial things like array bounds checking.
Yes, D's contracts are based on Eiffel. But they also went nowhere until D adopted them.
WalterBright•1mo ago
https://www.digitalmars.com/ctg/contract.html
mcdeltat•1mo ago
(Back in C++20 days I had a terrible habit of finding bugs in MSVC's implementations of metaprogramming features, after they claimed to be feature complete on C++20. Probably because people use these features less. Even now I occasionally receive emails about those bugs they've finally fixed.)