Skip to content

Commit 94f44dd

Browse files
[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.
1 parent 8db8628 commit 94f44dd

1 file changed

Lines changed: 5 additions & 4 deletions

File tree

source/meta.tex

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2867,18 +2867,19 @@
28672867
struct OptBool {
28682868
union { bool b; char c; };
28692869

2870-
// note: this assumes common implementation properties for \tcode{bool} and \tcode{char}:
2871-
// * \tcode{sizeof(bool) == sizeof(char)}, and
2870+
// note: this assumes common implementation properties for \tcode{bool}:
2871+
// * \tcode{bool} has the same object representation, value representation, and
2872+
// alignment requirements as \tcode{unsigned char}, and
28722873
// * the value representations for \tcode{true} and \tcode{false} are distinct
2873-
// from the value representation for \tcode{2}
2874+
// from the value representation for \tcode{char\{2\}}
28742875
constexpr OptBool() : c(2) { }
28752876
constexpr OptBool(bool b) : b(b) { }
28762877

28772878
constexpr auto has_value() const -> bool {
28782879
if consteval {
28792880
return std::is_within_lifetime(&b); // during constant evaluation, cannot read from \tcode{c}
28802881
} else {
2881-
return c != 2; // during runtime, must read from \tcode{c}
2882+
return std::bit_cast<char>(*this) != 2; // during runtime, must read the value representation
28822883
}
28832884
}
28842885

0 commit comments

Comments
 (0)