While implementing byte order conversion function for a structure, I found out that implementation violates DRY principle.
Here is the code snippet to show what I mean:
inline void FromHostByteorderToNetwork(ServerStatus& ss) {
ss.field0 = qToBigEndian<__int32>(ss.field0);
ss.field1 = qToBigEndian<__int16>(ss.field1);
//... 20+ more fields assigned in the same way
inline void FromNetworkByteorderToHost(ServerStatus& ss) {
ss.field0 = qFromBigEndian<__int32>(ss.field0);
ss.field1 = qFromBigEndian<__int16>(ss.field1);
//... 20+ more fields assigned in the same way
What I want: one routine, where I can pass name of template function (qToBigEndian/qFromBigEndian), with implementation like:
template <typename ByteConversionFunctionT>
inline void changeByteOrder(ServerStatus& ss) {
ss.field0 = ByteConversionFunctionT<__int32>(ss.field0);
ss.field1 = ByteConversionFunctionT<__int16>(ss.field1);
Important information:
Also, notice that ByteConversionFunctionT inside changeByteOrder is instantiated with different type: like __int32/__int16
in Qt headers qFrom/To is a template:
template <typename T> inline T qFromBigEndian(T source)
Can you suggest the way to do it, or maybe to obey KISS and duplicate code in order to avoid additional complexity?
One option would be to write a class template wrapper:
template <class T>
struct FromBigEndian
{
static T call(T source) { return qFromBigEndian(source); }
};
template <class T>
struct ToBigEndian
{
static T call(T source) { return qToBigEndian(source); }
};
template <template <class> class ByteConvertor>
void changeByteOrder(ServerStatus &ss)
{
ss.field0 = ByteConvertor<__int32>::call(ss.field0);
ss.field1 = ByteConvertor<__int16>::call(ss1.field1);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With