4

May one convert a char with the value not \0 and not \1 into bool using std::bit_cast? And if yes, what will the value of the resulting bool: true or false?

For example,

#include <bit>

constexpr bool x = [] {
    return std::bit_cast<bool>('\2');
}();

int main() {
    return x;
}

This program returns 2 in EDG and MSVC, 0 in GCC. And only Clang rejects it with the error:

<source>:3:16: error: constexpr variable 'x' must be initialized by a constant expression
/opt/compiler-explorer/clang-20.1.0/bin/../include/c++/v1/__bit/bit_cast.h:37:10: note: value 2 cannot be represented in type 'bool'

Online demo: https://gcc.godbolt.org/z/P6xPPn5Ez

Which implementation is correct here?

11
  • 4
    The behavior of a program that uses std::bit_cast<bool> on a value whose bit pattern doesn't correspond to the bit pattern of a valid bool value is undefined. The C++ standard doesn't impose any requirement on what the code in the question does. Commented May 11 at 10:00
  • 2
    @MartinBrown there is still a lot of historic C code around where only 0 is interpreted as false How much of that historic code uses std::bit_cast? Commented May 11 at 11:23
  • 1
    The answers are: no, no, n/a, and all of them. Commented May 11 at 11:37
  • 1
    or replace return std::bit_cast<bool>('\2'); with return '\2' != '\0'; Commented May 11 at 14:38
  • 1
    Proper way to cast to bool is static_cast. I sometimes use double-bang (!!) for fun and succinctness, but it's not good, and may fail, in case of any inconsistencies in the input type's interface. bit_cast has UB in cases where the source bit pattern doesn't have defined meaning in destination type. bool has only two values, with platform dependent bit patterns. So, technically bit_cast<bool> is almost always UB, unless from enum :bool types in which case the affirmationed static_cast is preferred. Commented May 12 at 10:59

1 Answer 1

1

The relevant section is [bit.cast]:

For the result and each object created within it, if there is no value of the object's type corresponding to the value representation produced, the behavior is undefined.

One can determine if there exist padding bits using std::has_unique_object_representations. If there are no padding bits, the object representation and the value representation are the same, and if a value is produced is not valid for that type, we have UB.

constexpr often helps due to the prohibition that language UB is disallowed. Specifically, that is [expr.const]:

an operation that would have undefined or erroneous behavior as specified in [intro] through [cpp]

The UB here is not included.

Therefore, assuming no padding bits, the original program is UB. All 3 compilers are correct.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.