приведение size_t * к hsize_t * - PullRequest
       68

приведение size_t * к hsize_t *

0 голосов
/ 15 января 2020

На моей платформе size_t и HDF5 hsize_t являются 64-разрядными целыми числами без знака, но это разные типы C ++ (один unsigned long, другой unsigned long long) и не могут использоваться взаимозаменяемо.

 using hsize_t = unsigned long long;
 void library_function(const hsize_t*);

 void client_code(std::vector<size_t> const&input)
 {
     library_function(input.data());     // error
 }

Итак, мой вопрос: требуется ли в этой ситуации преобразование

 void client_code(std::vector<size_t> const&input)
 {
     std::vector<hsize_t> tmp(input.size());
     std::transform(input.begin(), input.end(), tmp.begin(),
                    [](size_t x) { return hsize_t(x); });
     library_function(tmp.data());
 }

или я могу просто разыграть?

 void client_code(std::vector<size_t> const&input)
 {
     static_assert(sizeof(size_t)==sizeof(hsize_t),"!!");
     library_function(reinterpret_cast<const hsize_t*>(input.data()));     // correct?
 }

(это компилируется, но гарантированно ли работать правильно?)

1 Ответ

3 голосов
/ 15 января 2020

Доступ к значению через результирующий указатель reinterpret_cast является нарушением псевдонимов, если два типа действительно, вплоть до квалификации cv, отличаются не целыми типами char, которые не являются unsigned / signed версии друг друга. Поскольку вы сказали, что здесь есть два типа unsigned long и unsigned long long, это применимо к вашему делу.

Вы не можете использовать его, если хотите оставаться в рамках того, что определяет стандарт. Также нет способа набрать один целочисленный тип на другой, поэтому вам всегда нужно копировать (это может или не может быть оптимизировано компилятором).


Обычно вы можете сделать это работать на практике (даже если это неопределенное поведение в соответствии со стандартом) путем установки какого-либо флага компилятора, например -fno-strict-aliasing, который указывает компилятору не оптимизировать на основе гарантий, данных ему правилом псевдонимов (что может привести к ухудшению производительности ) или «скрывая» доступ нарушающего указателя от оптимизатора, помещая его в другую единицу перевода (если оптимизация времени соединения не используется). Смотрите также комментарий @ HolyBlackCat по этому вопросу.

Либо будет непереносимым. Например, другой компилятор (версия) может по умолчанию оптимизировать время компоновки или не поддерживать -fno-strict-aliasing или аналогичный.

...