Search code examples
c++language-lawyerreinterpret-cast

reinterpret_cast between char* and std::byte*


I'm reading type aliasing rules but can't figure out if this code has UB in it:

std::vector<std::byte> vec = {std::byte{'a'}, std::byte{'b'}};
auto sv = std::string_view(reinterpret_cast<char*>(vec.data()), vec.size());
std::cout << sv << '\n';

I'm fairly sure it does not, but I often get surprised by C++. Is reinterpret_cast between char*, unsigned char* and std::byte* always allowed?

Additionally, is addition of const legal in such cast, e.g:

std::array<char, 2> arr = {'a', 'b'};
auto* p = reinterpret_cast<const std::byte*>(arr.data());

Again, I suspect it is legal since it says

AliasedType is the (possibly cv-qualified) signed or unsigned variant of DynamicType

but I would like to be sure with reinterpret_casting once and for all.


Solution

  • The code is ok.

    char* and std::byte* are allowed by the standard to alias any pointer type. (Be careful as the reverse is not true).

    ([basic.types]/2):

    For any object (other than a base-class subobject) of trivially copyable type T, whether or not the object holds a valid value of type T, the underlying bytes ([intro.memory]) making up the object can be copied into an array of char, unsigned char, or std​::​byte ([cstddef.syn]).43 If the content of that array is copied back into the object, the object shall subsequently hold its original value.

    ([basic.lval]/8.8):

    If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined:

    • a char, unsigned char, or std​::​byte type.

    And yes you can add const.