c++alignmentreinterpret-casttype-punning

Converting a templated data into another templated data


I have a method returning a templated class and taking as argument another templated class such as :

template <class T, class U>
T caster(U* u)
{
    return reinterpret_cast<T>(u);  
}   

Compiling with an ARM compiler, i get a cast-align error returned by my compiler which understandable because in my example bellow, char and int do not have the same alignment. As i know that reinterpret_cast is not that such of a good practice, i tried the following changes :

template <class T, class U>
T caster(U* u)
{
    T tmp;
    std::memcpy(&tmp, u, sizeof(U));
    return tmp;
}

int main()
{
    int32_t test = 50000;
    auto tmp = caster<char, int32_t>(&test);
    return 0;
}

But this time i get a stack smashing detected error which is equivalent i believe to a kind of overflow.

What am I doing wrong ? Based on 2 unknown types, how can i properly cast U to T taking into account alignment ?


Solution

  • T tmp;
    std::memcpy(&tmp, u, sizeof(U));
    return tmp;
    

    The obvious issue here is that you're copying sizeof(U) bytes into T, even though T may be smaller or larger.

    If anything, it should be sizeof(T) or sizeof(tmp):

    template <class T>
    T caster(void* memory) {
        T tmp;
        // It's still possible that we cannot read sizeof(T) bytes from memory,
        // but that's on the caller, and at least we never smash the stack.
        std::memcpy(&tmp, memory, sizeof(T));
        return tmp;
    }
    

    Notice that what you're making here is a poor-man's std::bit_cast. It's one of the ways to do type punning in modern C++. reinterpret_cast virtually never is.

    See also