Как я могу безопасно разыграть long на соответствующий intX_t?
Вам не нужно разыгрывать.Преобразование неявное:
long x = 2;
long_t y = x;
Но вы можете использовать статическое приведение, если хотите быть явным:
long_t y = static_cast<long_t>(x);
Обман указателя подразумевает, что вы можете захотеть иметь дело собъект на месте.Это, конечно, требует, чтобы типы имели одинаковое представление, что является довольно разумным предположением, хотя и не гарантируется.Но даже предположение, технически недостаточное для того, чтобы косвенность через reinterpret_cast
было хорошо определено в соответствии со стандартом.
Технически можно использовать хранилище, создав объект нужного типа:
long_t temp = x;
long_t* reused_x = new(&x) long_t(temp);
После повторного использования вы можете конвертировать указатель в x
на лету, если вы не можете сохранить тот, который был возвращен путем размещения нового путем отмывания.Обратите внимание, что отмывание недостаточно без нового размещения.
long_t* converted = std::launder(reinterpret_cast<long_t*>(&x));
То же самое можно сделать в цикле с массивами:
template<class T, class F> // types To and From
T* reuse_array(F* first, F* last, T* d_first) {
for (F* ptr = first; ptr != last; ++d_first, (void) ++ptr) {
T value = *ptr;
::new (ptr) T(value);
}
return std::launder(reinterpret_cast<T*>(first));
}
Это можно сделать даже со структурами, использующими std::memcpy
пока они тривиально копируемы и разрушаемы.Достаточно хороший оптимизатор должен исключить копии .Обратите внимание, что время жизни x
закончилось и больше не может использоваться.
Существует предложение о введении std::bless
в язык, который должен устранить необходимость явного создания объектав подобных случаях.