Determine if reinterpret_cast is safe at compile time

Viewed 170

According to the reinterpret_cast page on cppreference.com, there are 11 conversions that

can be done with reinterpret_cast, except when such conversions would cast away constness or volatility.

So, my question is: is it possible to write a constexpr function like

template <typename T1, typename T2>
constexpr bool is_reinterpret_cast_safe() {
    // ...
}

that checks whether the conversion if allowed or not, based on those 11 points? Since compilers like GCC and Clang are able to check if the code breaks the strict aliasing rule, compiling with -fstrict-aliasing -Wstrict-aliasing, I think is should be possible somehow.

I know C++20 introduces std::bit_cast, but it is still not supported by any compiler. It could be useful to select between two casting functions at compile time

template <typename T1, typename T2>
T1 f_reinterpret_cast(T2 d) {
    static_assert(sizeof(T1) == sizeof(T2));
    return *reinterpret_cast<T1*>(&d); // could be undefined behavior;
}

template <typename T1, typename T2>
T1 f_memcpy(T2 d) {
    static_assert(sizeof(T1) == sizeof(T2));
    T1 n;
    std::memcpy(&n, &d, sizeof(T2)); // OK
    return n;
}

with SFINAE or if constexpr:

template <typename T1, typename T2>
T1 conv(T2 d) {
    if constexpr (is_reinterpret_cast_safe<T1, T2>())
        return conv_reinterpret_cast<T1, T2>(d);
    else
        return conv_memcpy<T1, T2>(d);
}

You may find the code on https://godbolt.org/z/Ex6GnP.

1 Answers

Compilers check the validity of a reinterpret_cast expression at compile time: aliasing rule violation happens when an object is accessed:

int i = 0;                                   //OK
double j* = reinterpret_cast <double*> (i);  //OK
double k = *j;                               //strict aliasing violation

It is not possible to check that a reinterpret_cast will not result in a pointer that can not be used to access the object it points to.

Related