c++language-lawyerc++20nullptrbit-cast

Can std::bit_cast convert to or from std::nullptr_t type?


Is it prohibited to use std::bit_cast for conversion to or from std::nullptr_t = decltype(nullptr) type? And if it is permitted, 1) must the result of std::bit_cast be the same as static_cast, 2) must the conversion back and forth return the original value?

I have tested the current compilers, and they all accept the following program without any warnings:

#include <bit>
#include <iostream>

int p = 0;
auto n = std::bit_cast<decltype(nullptr)>( &p );

int main() {
  std::cout 
    << (std::bit_cast<int*>(n) == static_cast<int*>(n))
    << ' '
    << (&p == std::bit_cast<int*>(n));
}

But the compilers diverge in how they treat the casts, which is visible from the output of the program:

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

Which implementation is correct here if any?


Solution

  • [basic.types.general]/4 defines value representation as "the set of bits in the object representation of T that participate in representing a value of type T". [conv.lval]/3.1 says that lvalue-to-rvalue conversion on a nullptr_t object produces a null pointer constant without even accessing its storage. It follows that the value representation of nullptr_t is necessarily empty and every bit in its object representation is a padding bit.

    That being the case, the object representation produced by a bit_cast to nullptr_t is entirely unspecified, and the bit_cast back has undefined behavior because every bit in the value representation produced is indeterminate and the indeterminate bit is not contained in an unsigned char or std::byte object.

    All three compilers are conforming.