C++20 Oxymoron: Constexpr Virtual
cppstories.com
cppstories.com
If you understand the true definitions `constexpr virtual` doesn't seem contradictory.
but they are not ?
- inline relaxes ODR which generally changes the linkage of the symbol (weak linkage when inline & exported, strong when not)
- adding virtual will always make your class have a vtable and your method overridable.
- constexpr make it possible to use in e.g. template arguments:
constexpr int foo() { return 123; }
std::array<int, foo()> arr;
that does not mean that the compiler cannot optimize - no matter how complex your program is, if the compiler has sufficiently advanced optimization passes, it should be able to precompute everything that is possible at compile timeNo?
proof: https://godbolt.org/z/W9MMGvTEz
proof at runtime (to make sure that the compiler doesn't "lie" about the size, we check the stack address of the variable constructed after the one with a virtual, and after the one without ; in the first case it's 16 bytes after, in the second 1 byte): https://godbolt.org/z/s11o9do4n ; basically in the simplest indirect measure possible that we can make of the object's size, the vtable is there
if that was not the case, it would mean that the size of the type would vary, which would break a lot of expectations.
Imagine the following:
class obj { virtual int space_used() { return sizeof(obj); } };
class sub1 : obj { int space_used() override { return sizeof(sub1); } };
it would be very normal for someone to call `space_used();` at some point, and use that size at another point (with a different instance), for instance for allocation ; if that size was to change because that instance was "optimized" by the compiler, that could wreak havoc.Would you happen to have a sharable example of this occurring? I'd be curious to see what heuristics GCC is using. Also, what the conditional is on...is it still on the vtable, but just avoiding the indirect call?
http://hubicka.blogspot.com/2014/01/devirtualization-in-c-pa...
A compiler could legally remove the vpntr if not necessary. In practice this only happens for purely local objects as current compilers do not implement the necessary interprocedural data layout transformation.
In the meanwhile, how is C++ lifetime profile doing, is it useable yet?
I know C++ pretty well, but I'd pick Rust (or Zig) for my next project.
Declaring a method const tells the compiler that that method won’t change the object.
Declaring something constexpr tells the compiler that if its arguments are known at compile time then it will always return the same result and may be a candidate for “invocation” at compile time.
The fact that the keywords both contain the string “const” is a consequence of the English language.
As for inference, maybe in the example, although in most code bases with binary libraries it would be useless anyway.
https://brevzin.github.io/c++/2019/01/15/if-constexpr-isnt-b...
https://www.goodreads.com/quotes/40705-but-the-plans-were-on...
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n361...
Admittedly there are a ton of things I don't like about D and overall I find the language to be quite unprincipled and just a kitchen sink of poor mismatched features... but certainly there are some things D does exceptionally well and C++ should have learned from them to avoid about a decade worth of lost productivity.
Things like modules, ranges, template constraints, static if, compile time execution are all much cleaner in D than what C++ has and with every new C++ standard it turns out that things are broken, defect reports have to be published, there are serious quality of implementation issues and the features just don't work as well in actual production grade projects compared to the tiny and artificial examples one reads in a blog post to show off the feature.
But it's taboo to learn from D, or virtually any other language, with the mantra that "C++ is not like other languages, it's just soooo unique and special that what works for language Foo won't possibly work for C++." and so instead C++ has to reinvent everything in a half-assed manner and repeat many mistakes that others have already learned from.
> The feature provides a single syntax with three distinct semantics, depending on the context of use.
Following immediately after
> ...fundamentally flawed, and its adoption would be a disaster for the language.
as it does, one could almost think he means that's a bad thing. And then:
> This will make programs harder to read, understand, maintain, and debug.
Yeah, so what -- isn't that what C++ is all about?
But I do also know from experience that walking the line of evolving language features in a compiler taking into consideration prior legacy decisions is extremely difficult.
I think more than it being a pissing contest, I interpret there are practical considerations the C++ Standards Committee is considering in terms of performance, ease of implementation, and interaction with legacy features.
In fact, he has failed to avoid certain C++ features even though he heavily argued against them.
I been in the C/C++ world for more than a decade.
The seeming simplicity of C++ spec in comparison to "modern" languages hides many unfathomable corner cases, and non-obvious interactions of language features
This is the first time I have seen someone claim that the C++ spec seems simple. As far as I know, it is the most complex language ever designed (joke/esoteric languages notwithstanding).
The insanity really began when attempt to further formalise, and narrowly specify the language revealed glaring gaps of the basic spec, and a decade+ period of haphazard fixes to the standard started.
C++98 had the same value categories (lvalue and rvalue) as C, but already more complex interactions between these and various other language features, because of references if nothing else.
Then, C++ has not one but two kinds of pointers - C-style pointers and references, which each interact with other languages differently.
C++ has the most complex function overloading rules of any language. Made all the more complex by the special interaction between single-parameter constructors and function overloading. Operator overloading adds yet another layer of complexity, being slightly different than function overloading rules.
C++ has exceptions and destructors and special interactions between them. Exceptions also interact with the reference and type specifier system in complex ways. C++98 even had exception specifiers which also have interactions with the type system in general.
C++ has templates, with the myriad complex rules for their syntax (e.g. the little known second meaning of the keyword "template"), for name resolution inside template definitions, for template interactions with the linker. SFINAE is also a famously hard to understand rule, that interacts so nicely with overload resolution that it turns the compilation process into a turing-complete language of its own.
C++ has namespaces, which interact with name resolution and thus templates and overload resolution in several ways. In the same vein, it has private, public, protected, and friend, all interacting with name resolution.
C++ supports multiple inheritance, with complex rules for how objects are constructed in the presence of multiple super classes.
C++ has 3 different ways of initializing member variables, with defined interactions between them (in-place, constructor initiator list, constructor body).
C++ inherits C's pre-processor, while adding new ways for it to interact with linkage rules (because of templates, default constructors/destructors).
If you generalize that to variables, you get 18: https://accu.org/journals/overload/25/139/brand_2379
Still, the cruft accumulates, and I dread the day when the language will become recognizably C++ish. Feels like things are getting out of control already - most C# programmers I've met know/use barely any of the features introduced after C# 6.0. (They're pretty good, though. The features, I mean. But the programmers also)
?
A lot of the C++ spec is nailing these down (or giving you a tool to choose). In that it’s a lot like IEEE 754: very simple, but then with page after page of “oh, so here’s a non-obvious consequence and how it must be handled.”