Я только что присоединился к команде, которая имеет тысячи строк кода, таких как:
int x = 0;
x=something();
short y=x;
doSomethingImportantWith(y);
Компилятор выдает приятные предупреждения: «Преобразование значения типа бит XX в« короткий »вызывает усечение. Мне сказали, что нет случаев, когда действительно происходит усечение, но я серьезно сомневаюсь в этом.
Есть ли хороший способ вставить чеки в каждый случай, имеющий эффект:
if (x>short.max) printNastyError(__FILE,__LINE);
перед каждым назначением? Выполнение этого вручную займет больше времени и усилий, чем я хотел бы использовать, а написание сценария, который читает предупреждения и добавляет эти данные в правильный файл, а также необходимые включения, кажется излишним — тем более, что я ожидаю, что кто-то уже сделал это (или что-то подобное).
Меня не волнует производительность (на самом деле) или что-то другое, кроме как знать, когда возникают эти проблемы, поэтому я могу либо исправить только те, которые действительно имеют значение, либо я могу убедить руководство в том, что это проблема.
Вы можете попробовать скомпилировать и запустить его со следующим уродливым хаком:
#include <limits>
#include <cstdlib>
template<class T>
struct IntWrapper
{
T value;
template<class U>
IntWrapper(U u) {
if(u > std::numeric_limits<T>::max())
std::abort();
if(U(-1) < 0 && u < std::numeric_limits<T>::min()) // for signed U only
std::abort();
value = u;
}
operator T&() { return value; }
operator T const&() const { return value; }
};
#define short IntWrapper<short>
int main() {
int i = 1, j = 0x10000;
short ii = i;
short jj = j; // this aborts
}
Очевидно, это может нарушить код, который проходит short
в качестве аргумента шаблона и, вероятно, в других случаях, поэтому определите его там, где он нарушает сборку. И вам может понадобиться добавить перегрузки операторов, чтобы обычная арифметика работала с оберткой.
Вероятно, вы можете написать плагин для gcc, чтобы обнаруживать эти усечения и отправлять вызов функции, которая проверяет, что преобразование безопасно. Вы можете написать эти плагины в С или же питон. Если вы предпочитаете использовать Clang, он также поддерживает запись плагины.
Я думаю, что самый простой способ сделать это — сделать так, чтобы плагин конвертировал небезопасный бросок из int
в short
вызвать функцию _convert_int_to_float_fail_if_data_loss(value)
, Я оставлю это в качестве упражнения для читателя, как написать такой плагин.