From 94f44dd20c65115effcd682276273421919bfd17 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Mon, 9 Mar 2026 12:09:29 +0800 Subject: [PATCH] [meta.const.eval] Use `bit_cast` in the example to avoid UB It is unclear whether the reading an inactive `char` variant member can be well-defined. General rules for out-of-lifetime objects disallows this, but [basic.lval]/11 arguably allows reading the whole union via such a `char` glvalue. In any case, it seems better to use some more uncontroversial way to read the value representation of `OptBool` in the example during runtime. [basic.fundamental]/10 requires `bool` to have the same object representation, value representation, and alignment requirements as an implementation-defined unsigned integer type. Presumably, the example essentially expected such an underlying-like type to be `unsigned char`. Since `unsigned char` can't have padding bits, it would be sufficient to infer that `bool` can't have padding bits either on common implementations. As a result, `bit_cast` to `char` or `unsigned char` can work. This PR clarifies the assumptions for `bool` in comments and switch to use `bit_cast` to avoid arguable UB. --- source/meta.tex | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/source/meta.tex b/source/meta.tex index 48510a4e39..5da7f5f9c6 100644 --- a/source/meta.tex +++ b/source/meta.tex @@ -2867,10 +2867,11 @@ struct OptBool { union { bool b; char c; }; - // note: this assumes common implementation properties for \tcode{bool} and \tcode{char}: - // * \tcode{sizeof(bool) == sizeof(char)}, and + // note: this assumes common implementation properties for \tcode{bool}: + // * \tcode{bool} has the same object representation, value representation, and + // alignment requirements as \tcode{unsigned char}, and // * the value representations for \tcode{true} and \tcode{false} are distinct - // from the value representation for \tcode{2} + // from the value representation for \tcode{char\{2\}} constexpr OptBool() : c(2) { } constexpr OptBool(bool b) : b(b) { } @@ -2878,7 +2879,7 @@ if consteval { return std::is_within_lifetime(&b); // during constant evaluation, cannot read from \tcode{c} } else { - return c != 2; // during runtime, must read from \tcode{c} + return std::bit_cast(*this) != 2; // during runtime, must read the value representation } }