I am writing a generic update function for EEPROM which compares old value with new one and then if values differ writes new one to eeprom. This is the function:
template <typename T>
void update(uint16_t update_address, T& update_value)
{
// Do not attempt to read until device is ready
while (!TM_I2C_IsDeviceConnected(EEPROM_I2Cx_, EEPROM_ADDRESS)) {}
T current_value;
read(update_address, current_value);
if (memcmp(¤t_value, &update_value, sizeof(T)) != 0)
{
// Do not attempt to write until device is ready
while (!TM_I2C_IsDeviceConnected(EEPROM_I2Cx_, EEPROM_ADDRESS)) {}
write(update_address, update_value);
}
}
The problem is comparison. I read that due to padding the variables might differ if they are structures in certain cases and its generally bad idea to use memcmp to compare two structures. But I want my function to be generic. I could assume that "==" operator is defined and use
template <typename T>
void update(uint16_t update_address, T& update_value)
{
// Do not attempt to read until device is ready
while (!TM_I2C_IsDeviceConnected(EEPROM_I2Cx_, EEPROM_ADDRESS)) {}
T current_value;
read(update_address, current_value);
if (current_value != update_value)
{
// Do not attempt to write until device is ready
while (!TM_I2C_IsDeviceConnected(EEPROM_I2Cx_, EEPROM_ADDRESS)) {}
write(update_address, update_value);
}
}
but I wonder if in this case a "==" operator is REALLY needed. After all I am really just comparing raw bytes, no logic involved (i.e. uint8_t boolean might be true in both structs even if one is 1 and other 100 and this should be handled properly, but in this case it doesn't matter at all as it should be one and same structure byte-wise), but that padding thing has thrown me off a little. My question therefore is Is it okay in this particular case to use memcmp (T can be any type, probably in a lot of cases a structure) and can padding cause any problems or should I assume or rather explicitly demand "==" operator to be defined prior to using the function?
Best Answer
If you really want your template class to be generic (and it seems you want to), you should be using the == operator. Indeed, there might be uninitialized padding bytes in the struct, and your comparison with memcmp would return false even if the fields all have the same value. Of, course, this requires the == operator to be appropriately defined for the underlying type, but that is a safer assumption than considering all bytes of the struct have significance.
This choice has the following consequences: