3 ms·
What is non-obvious about “[[indeterminate]]”? That terminology has been used throughout the standards in exactly this context for ages. This just makes it expl
by jandrewrogers 7mo ago
What is non-obvious about “[[indeterminate]]”? That terminology has been used throughout the standards in exactly this context for ages. This just makes it explicit instead of implicit so that the compiler can know your intent.
- ozgrakkurt 7mo agoI know roughly what indeterminate means in english but it is not obvious to me when I see something like this in code. So I would have to look it up and be very careful about it since I can break something easily in C++. This just makes things more difficult from the perspective of using/learning the language. Similar problem with "unsequenced" and "reproducible" attributes added in c. It sounded cool after I took the time to learn exactly (/s) what it means. But it is not worth the time to learn it. And it is not worth the cognitive load it will put on people that will read the code later imo.
- Joker_vD 7mo agoI wonder if you're fine with const, constexpr and volatile also being things. I mean, "const" really doesn't mean what one would naively think (that's what "constexpr" is actually for) and the semantics of "volatile" are also widely misunderstood.
- tialaramex 7mo agoNope, not only is C++ const not a constant, C++ constexpr isn't a constant either, and C++ constinit isn't a constant, C++ consteval is closest, but it's only available for functions. const int a = 10; // Just an immutable variable named a constexpr int b = 20; // Still an immutable variable named b static constinit int c = 30; // Now it isn't even immutable For functions const says this function promises it doesn't change things, constexpr says this function is shiny and modern and has no other real meaning (hence "constexpr all the things" memes, you might as well) but consteval does mean that we're promising this must always be evaluated at compile time, so the evaluation is frozen by runtime, however only a function can have this label. Volatile is a mess because what you actually want are the volatile intrinsics, indeed you might want more (or fewer) depending on the target. If your target can do single bit hardware writes it'd be nice to provide an intrinsic for that, rather than hoping you can write in code REG |= 0x40 and have that write a single bit... which on platforms which do not have this single bit write feature that's going to compile to an unsynchronized read-modify-write which may cause problems. However instead of having intrinsics C's volatile was hacked into the type system instead and C++ tries to keep that.
- functional_dev 7mo agospot on... that difference between evaluation and storage is exactly why C++ is so hard to keep in my head I thought constexpr was a hard physical constant, but in reality it's a weird hybrid this visualisation helped me to wrap my head around it - https://vectree.io/c/c-constness-and-evaluation-qualifiers https://vectree.io/c/c-constness-and-evaluation-qualifiers
- Joker_vD 7mo agogroans See, and that's why I'm personally fine with [[indeterminate]], etc: all of this is already a finely-splitted hairy mess and I'd rather not see even more keywords introduced if we can just use attributes instead. And yeah, it would probably be nice to also have some sane intrinsics to provide memory_order_consume semantics... but what can you do.
- ozgrakkurt 7mo agoConst, constexpr etc. Are mandatory to understand at this point. That situation doesn’t justify adding more things imo
- jcalvinowens 7mo agoConsume is dead. Long live acquire! But seriously, it is interesting how C++ is completely abandoning the concept. My handwavy understanding is that on some more specialized hardware acquire is substantially more expensive than consume.
- Joker_vD 7mo agoIf by "more specialized hardware" you mean "everything that is not x86". Its main intended use is (was?) for chained loads and rcu_dereference(), where hardware does not require an explicit memory fence between loads like ldr x8, [x8] # load a pointer from memory ldr x1, 16[x8] # load a field through that pointer or turning the second load into "ldar" — there is quite a visible data dependency between two registers. But compilers usually puts a barrier there anyway.
- saagarjha 7mo agoI mean there's a sibling comment that literally says that the word was chosen to be mysterious and make people look up what it means