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