Однако, такой код может привести к ошибке трансляции в том случае, если T является неперемещаемым. В твоем ЦБ должны присутствовать проверки на перемещаемость, копируемость и возможность размена состояний.
Если T можно копировать, но не перемещать, использовать стоит оператор копирования.
И только если ни копировать, ни перемещать T нельзя, следует пользоваться деструктором и размещающим конструктором.
Я бы рекомендовал все три действия оформить в виде перегрузок шаблона функции со SFINAE, чтобы для любого T включалась только одна конкретная перегрузка шаблона.
Также интересно понять что такое эти size и maxSize. А
Мне интересно понять, для чего существует первый участок кода, который оформлен в if (size < maxSize) и для чего существует второй - который под первым.
А так же - почему функция называется add и имеет такие параметры.
Если бы длины типов были разные, то wide type обрезался до длины narrow type и то же самое побитовое копирование.
Интерес в том, что даже unsigned char не подходит для подмены. Стандартом разрешены только char и std::byte.
Ok, let's get truly pedantic. After reading this, this and this, I'm pretty confident that I understand the intention behind both Standards.
So, doing reinterpret_cast from std::uint8_t* to char* and then dereferencing the resulting pointer is safe and portable and is explicitly permitted by [basic.lval].
However, doing reinterpret_cast from char* to std::uint8_t* and then dereferencing the resulting pointer is a violation of strict aliasing rule and is undefined behavior if std::uint8_t is implemented as extended unsigned integer type.
Нет, если вы не вызвали конструктор и обратились к объекту, вы схлопочете UB, формально говоря.
Да и какой смысл в том, чтобы навыделять памяти, а конструкторы не вызывать? Это нарушает принцип RAII как минимум.
Кстати, именно статической памяти я в вашем коде не увидел.