jeudi 20 avril 2017

type punning with template

I had to check someone's clumsy code that used 20+ unions and according number of methods that were punning and copy data from and to an byte array, in order to implement those methods through template (second for a char)

template <class T> class type_punner
{
    T& p;
    unsigned char* pun;

public:
    type_punner(T&  ref): p (ref), pun(reinterpret_cast<unsigned char*>(&p))
    {
        static_assert(std::is_pod<T>::value, "type_punner can be used only for POD");
    }


    inline unsigned char& at(std::size_t  i)
    {
#ifdef QT_DEBUG
        if(!(i < size())) throw std::out_of_range( __FUNCTION__ );
#endif
#if (Q_BYTE_ORDER == Q_LITTLE_ENDIAN)
        return pun[i];
#else
        return pun[size() - i - 1];
#endif
    }

    inline unsigned char& reverse_at(std::size_t  i)
    {
#ifdef QT_DEBUG
        if(!(i < size())) throw std::out_of_range(__FUNCTION__);
#endif
#if (Q_BYTE_ORDER == Q_LITTLE_ENDIAN)
        return pun[size() - i - 1];
#else
        return pun[i];
#endif
    }

    // = 0 is  LSB
    inline unsigned char& operator[](std::size_t  i)
    {
        return at(i);
    }

    inline std::size_t size()
    {
        return sizeof(T);
    }
};

Only what I worry about that if I'm staying standard compliant and assigning new values via returned references is valid.

Aucun commentaire:

Enregistrer un commentaire