<div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr">On Sat, Jun 20, 2020 at 5:33 PM Ray Zhang <<a href="mailto:peifeng2005@gmail.com">peifeng2005@gmail.com</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr">Hi Arthur,<div>First of all, it's an honor. I remember watching your "Allocator is a handle to a heap" c++now talk a while ago :)</div></div></blockquote><div>Hey, thanks! :) Don't take anything I say as gospel when it comes to cfe-dev, though. :)</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>Second, you're right - I forgot about DerivedToBase or BaseToDerived in the above example. Regarding the statement regarding unpresentable as a non-C-style cast, in <a href="https://en.cppreference.com/w/cpp/language/explicit_cast" target="_blank">the standard</a> it breaks down C-style casts as a cascading attempt to use const/static/reinterpret, or combinations of them. Here's an example of private base: <a href="https://godbolt.org/z/5STynJ" target="_blank">https://godbolt.org/z/5STynJ</a>.<br></div></div></blockquote><div><br></div><div>Yes, but notice where cppreference says "static_cast <i style="font-weight:bold">with exceptions</i>"; I was talking about the exceptions.</div><div>Here's an example where C-style cast and reinterpret_cast do different things, but any other kind of cast (e.g. static_cast) is ill-formed.</div><div><a href="https://godbolt.org/z/if7Pis">https://godbolt.org/z/if7Pis</a><br></div><div>Clang gives a warning suggesting that you replace the reinterpret_cast with a static_cast, but of course if you actually did that, the code wouldn't compile anymore.</div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>Third, I didn't check for C++20 for union casts, but I'm guessing it "working" is a side-effect of the parens-initialization of aggregates allowing narrowing conversions. Here's a link that shows that the example in the C++20 mode you showed is not equivalent to a C-style cast assignment which is just an alias for (union U) {.x = x}: <a href="https://godbolt.org/z/7LJCQy" target="_blank">https://godbolt.org/z/7LJCQy</a>.</div></div></blockquote><div><br></div><div>Ah, yes, you're right. With `(U)y`, GCC is calling the same pseudo-constructor as `U(y)`, which is supposed to just implicitly convert the float to an int and initialize the first member of the union, completely ignoring the fact that `y` is a float</div><div>This appears to be actually the correct behavior in C++20, even though it seems pretty crazy. (In other words, C++20's new union syntax doesn't follow the same overload-resolution-ish rules as C++17's std::variant.) Textual support:</div><div><a href="http://eel.is/c++draft/expr.cast#4">http://eel.is/c++draft/expr.cast#4</a> says that (U)y should behave the same as static_cast<U>(y) if possible, and<br></div><div><a href="http://eel.is/c++draft/expr.static.cast#4">http://eel.is/c++draft/expr.static.cast#4</a> says that static_cast<U>(y) should behave the same as U(y), which (new in C++20) should behave the same as U{.x = y}.<br></div><div><br></div><div>Here's a pared-down example where the two fields of the union have utterly different types, so the silent implicit conversion fails instead of succeeding. <a href="https://godbolt.org/z/9wVX6B">https://godbolt.org/z/9wVX6B</a></div><div>Apparently Clang just doesn't implement this C++20 rule yet; once it does, Clang's behavior should end up matching GCC's.</div><div><br></div><div>...Oh, and wait a minute! The first sentence of the documentation you linked says, "A cast to a union type is <i><b>a C extension not available in C++</b></i>."  So that explains why neither of us could reproduce the documented behavior! :)  Now here's a Godbolt showing the same code compiled as C++ (where it initializes the first field of the union) and C-with-extensions (where it initializes the second field because that field is a float).</div><div><a href="https://godbolt.org/z/heN2Fb">https://godbolt.org/z/heN2Fb</a><br></div><div>And here's Clang, reproducing GCC's behavior in C-with-extensions but failing to implement C++20 yet:</div><div><a href="https://godbolt.org/z/dY6ti8">https://godbolt.org/z/dY6ti8</a><br></div><div><br></div><div>–Arthur</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">
</blockquote></div>
</blockquote></div></div></div></div></div></div></div></div></div></div>