LifeEXE | Unreal Engine | CG
1.89K subscribers
384 photos
470 videos
423 links
Download Telegram
📕 Всем привет, всем привет! 📕

В эфире рубрика выходного дня: Воскресный C++ 🦊

Numeric limits в стандарте C++ и в Unreal Engine
На Boosty и Patreon расширенная статья с множеством интерактивных примеров в Compiler Explorer


🔤🔤🔤🔤🔤🔤🔤🔤 🔤

std::numeric_limits в C++ — это стандартный шаблонный класс, который предоставляет информацию о свойствах числовых типов, например:

🔤Минимальные и максимальные значения.
🔤Точность в десятичных знаках.
🔤Специальные значения: infinity, quiet_NaN, signaling_NaN и другие.

Полная спецификация на cppreference.com

Простейший пример использования:
#include <limits>
#include <print> // C++23

int main()
{
std::println("Max int: {}", std::numeric_limits<int>::max());
std::println("Min double: {}", std::numeric_limits<double>::min());
std::println("Lowest float: {}", std::numeric_limits<float>::lowest());
std::println("Double epsilon: {}", std::numeric_limits<double>::epsilon());
return EXIT_SUCCESS;
}


Ключевые особенности
⬇️

Безопасность
🔤Использование шаблонов позволяет компилятору проверять корректность типов на этапе компиляции, предотвращая ошибки.

Вместо «магических чисел» (например, 2147483647 для int), вы используете std::numeric_limits<int>::max(). В итоге код становится более читаемым и переносимым (платформонезависимым).

Портируемость
🔤Работает с любым числовым типом — int, float, double, uint64_t, а также с пользовательскими числовыми типами, если для них существует специализация шаблона numeric_limits .

Чистота кода
🔤Сразу видно, что речь о границе типа.

Когда реально нужен ⬇️

🟢 Для инициализации переменных максимальным или минимальным значением типа. Например, при поиске минимума/максимума в массиве.
🟢 Для проверки переполнения или выхода за пределы диапазона.
🟢 Для шаблонного кода, где тип неизвестен заранее.
🟢 Спецзначения: бесконечность и NaN.

💡 Дополнительно полезно почитать про:
🔤Saturation arithmetic
🔤std::add_sat


🔤🔤🔤🔤🔤🔤 🔤🔤🔤🔤🔤🔤

В Unreal Engine имеется собственный шаблон TNumericLimits<T> — это аналог std::numeric_limits, реализованный в движке.

Заголовочный файл находится по адресу: Runtime/Core/Public/Limits.h

Применение абсолютно аналогичное, как и в стандартном C++:
#include "Math/NumericLimits.h"
#include "Logging/StructuredLog.h"

DEFINE_LOG_CATEGORY_STATIC(LogNumLimitsTest, All, All);

void NumLimitsTest()
{
const int32 MaxInt = TNumericLimits<int32>::Max();
const int32 MinInt = TNumericLimits<int32>::Min();

const float MaxFloat = TNumericLimits<float>::Max();
const float MinFloat = TNumericLimits<float>::Min();

UE_LOGFMT(LogNumLimitsTest, Display, "Int32: Min={0}, Max={1}", MinInt, MaxInt);
UE_LOGFMT(LogNumLimitsTest, Display, "Float: Min={0}, Max={1}", MinFloat, MaxFloat);
}


💡Согласно последним рекомендациям, в коде проектов под Unreal Engine можно использовать и стандартный std::numeric_limits — читаем раздел Use of standard libraries. Поэтому можно выбирать любой подходящий под вашу конкретную ситуацию шаблон.

Всем чистого кода 🤘

🔤🔤🔤🔤🔤🔤🔤

🤝 Поддержать:
Patreon | Boosty | PayPal

Ресурсы:
GitHub | X | LifeEXE School | Itch | Wiki | Курс по UE

#code #cpp #code_hints #lifeexeEDU #unrealengine #ue5 #gamedev #lifeexe #lifeexecode #best_practice #numeric_limits #clean_code
Please open Telegram to view this post
VIEW IN TELEGRAM
6🔥241692🦄1
📕 Всем привет, всем привет! 📕

В эфире рубрика выходного дня: Воскресный C++ 🦊

Написал большую статью на тему:
«Asserts в стандарте C++ и в Unreal Engine»

❗️ На Boosty и Patreon полная версия с множеством примеров!


По традиции сначала разбираем как все работает на чистом
C++, а потом смотрим, что происходит в Unreal Engine
.

🔤🔤🔤🔤🔤🔤

Assertions — это утверждения, проверяющие предположения программиста о корректности кода. Они помогают выявлять ошибки и документировать инварианты.

Инвариант — это условие, которое должно быть истинным всегда в определённом контексте.

Зачем нужны assertions?
🔤Раннее выявление логических ошибок
🔤Документация ожиданий внутри кода
🔤Обеспечение корректности API

Виды assertions
🔤Времени выполнения — runtime assertions
🔤Времени компиляции — compile-time assertions

🔤🔤🔤🔤🔤🔤🔤🔤 🔤

В стандартном C++ основной инструмент для реализации утверждений — это макрос препроцессора assert, определенный в заголовочном файле <cassert> :

🔤Если выражение истинно — ничего не происходит, и выполнение программы продолжается.
🔤Если выражение ложно — макрос assert выводит диагностическое сообщение в стандартный поток ошибок stderr и немедленно завершает программу путем вызова функции std::abort() ➡️

double div(double numerator, double denominator) 
{
assert(denominator != 0.0);
return numerator / denominator;
}


Стандартный макрос assert не имеет встроенного параметра для пользовательских сообщений. Однако существуют две распространенные идиомы для добавления диагностики, которая будет выведена в диагностическом сообщении в случае сбоя ➡️

assert(divisor != 0 && "Divisor cannot be 0");
assert(("Divisor cannot be 0", divisor != 0));


Распространенная ошибка при использовании assert — это включение в проверяемое выражение кода с побочными эффектами.

Проблема в том, что когда определен макрос NDEBUG, все выражение внутри assert удаляется из кода. Это может привести к тому, что логика программы в отладочной и релизной сборках будет отличаться.

⚠️ Пример того, как делать НЕЛЬЗЯ:
assert(InitializeSubsystem());


✔️ Правильный подход — всегда отделяем действие от проверки:
[[maybe_unused]] const bool bSuccess = InitializeSubsystem();
assert(bSuccess);


🔤🔤🔤🔤🔤🔤 🔤🔤🔤🔤🔤🔤

Unreal Engine расширяет стандартный макрос assert , добавляя дополнительные возможности к рантайм проверкам, Имеются следующие семейства: check, verify, ensure.

🔤🔤🔤🔤🔤

Семейство check является прямым эквивалентом стандартного assert в Unreal Engine. Сбой check указывает на критическую ошибку в программе, и выполнение немедленно останавливается ➡️

void AMyActor::CalculateJumpVelocity(AActor* JumpTarget, FVector& JumpVelocity)
{
check(JumpTarget != nullptr);
}


Остальные макросы данного семейства: check, checkf, checkSlow, checkfSlow, checkCode, checkNoEntry, checkNoReentry, checkNoRecursion, unimplemented

🔤🔤🔤🔤🔤🔤

Следующее семейство макросов является решением проблемы побочных эффектов. Выражение внутри макроса verify выполняется всегда, независимо от конфигурации сборки.

Полный список макросов: verify, verifyf, verifySlow

🔤🔤🔤🔤🔤🔤

Данное семейство макросов используется для сообщения о нефатальных ошибках. Программа не завершает работу, а отправляет отчет со стеком вызовов в Crash Reporter и продолжает выполнение: ensure, ensureAlways, ensureMsgf, ensureAlwaysMsgf

🔤🔤🔤🔤🔤 🔤🔤🔤🔤

🔤Можно проверить на этапе компиляции → static_assert
🔤Критическая ошибка + нет побочных эффектов → check
🔤Критическая ошибка + есть побочные эффекты → verify
🔤Дорогая проверка только для отладки → checkSlow
🔤Некритическая ошибка, продолжаем работу → ensure
🔤Недостижимый код → checkNoEntry или unimplemented
🔤Защита от рекурсии → checkNoRecursion
🔤Защита от повторного вызова → checkNoReentry

В статье на Boosty и Patreon подробнее про каждый из макросов и static_assert


Всем чистого кода 🤘

🔤🔤🔤🔤🔤🔤🔤

🤝 Поддержать:
Patreon | Boosty | PayPal

Ресурсы:
GitHub | X | LifeEXE School | Itch | Wiki | Курс по UE

#code #cpp #code_hints #lifeexeEDU #unrealengine #ue5 #gamedev #lifeexe #lifeexecode #best_practice #assert #clean_code
Please open Telegram to view this post
VIEW IN TELEGRAM
21🔥3810👍95🦄11