вторник, 13 мая 2025 г.

[prog.c++] Введение в C++ типов std2::uint*_t, std2::int*_t, std2::float_t, std2::double_t?

Пост навеян флеймообразующей статьей с Хабра под названием "Как Мэтт Годболт «продал» мне Rust (рассказав о C++)" (которая является переводом статьи Matt Godbolt sold me on Rust (by showing me C++)). Сама статья мне не нравится тем, что на C++ навешивают собак, унаследованных из чистого Си. Да еще и демонстрируют использование приемов, за применение которых в коде надо бы отрывать руки (я про вызов atoi для выделения числа из строки).

Однако, не смотря на то, что неявное преобразование разных целочисленных типов между собой C++ унаследовал из Си и ругать за это безобразие прежде всего следует Си, эта проблема актуальна для C++ного кода. Что лично мне сильно не нравится и о чем я уже не раз говорил.

А раз проблема для C++ актуальна, то было бы хорошо ее решить.

Внезапно™ подумалось, что сделать это может быть не так уж и сложно.

Нужно ввести новые стандартные типы:

  • std2::int8_t, std2::int16_t, std2::int32_t, std2::int64_t;
  • std2::uint8_t, std2::uint16_t, std2::uint32_t, std2::uint64_t;
  • std2::int_fast8_t, std2::int_fast16_t, std2::int_fast32_t, std2::int_fast64_t;
  • std2::uint_fast8_t, std2::uint_fast16_t, std2::uint_fast32_t, std2::uint_fast64_t;
  • std2::int_least8_t, std2::int_least16_t, std2::int_least32_t, std2::int_least64_t;
  • std2::uint_least8_t, std2::uint_least16_t, std2::uint_least32_t, std2::uint_least64_t;
  • std2::uintmax_t
  • std2::uintptr_t
  • std2::float_t
  • std2::double_t

Главным (и, возможно, единственным) отличием от их старых собратьев будет то, что компилятор будет запрещать неявные преобразования значений между этими типами или типами из предыдущих стандартов C++ (включая унаследованные из Си и, ИМХО, совершенно бесполезные в современном мире short, int, long и пр.) Т.е. если мы написали так:

void f(std2::uint32_t n) {...}

То компилятор не позволит нам сделать так:

f(-1);

или так:

f(1.2);

или так:

int i = some_calculation();
f(i);

и даже так:

std2::uint_fast32_t r = another_calculation();
f(f);

То, что новые типы будут определены в новом пространстве имен, позволит не ломать старый код.

Если же в старом коде использовались std::int*_t и мы захотели адаптировать его под новый стандарт, то достаточно будет просто заменить std:: на std2:: простым контекстным поиском.

Мне кажется, что добавление таких типов сделает программирование на C++ более безопасным и предсказуемым с достаточно небольшими затратами.

А вот в то, что в C++ когда-нибудь введут запрет на неявные преобразования между старыми целочисленными типами я не верю. Так и будем жить обмазавшись этим древним говном.