Распространяется ли правило наказания типа «приведение к первому элементу стандартного макета» на массивы? - PullRequest
0 голосов
/ 07 июня 2018

В частности, я оборачиваю C API в дружественную оболочку C ++.API C имеет довольно стандартную форму:

struct foo {...};
void get_foos(size_t* count, foo* dst);

И то, что я хотел бы сделать, это сохранить себе дополнительную копию, передав массив с типизированным перфоратором непосредственно в C api с кучей проверок работоспособности static_assert().

class fooWrapper {
  foo raw_;
public:
   [...]
};

std::vector<fooWrapper> get_foo_vector() {
  size_t count = 0;
  get_foos(&count, nullptr);

  std::vector<fooWrapper> result(count);

  // Is this OK?
  static_assert(sizeof(foo) == sizeof(fooWrapper), "");
  static_assert(std::is_standard_layout<fooWrapper>::value, "");
  get_foos(&count, reinterpret_cast<foo*>(result.data()));

  return result;
}

Насколько я понимаю, это допустимый код, поскольку все доступные области памяти индивидуально соответствуют правилу, но я 'Я хотел бы подтвердить это.

Редактировать: Очевидно, что до тех пор, пока reinterpret_cast<char*>(result.data() + n) == reinterpret_cast<char*>(result.data()) + n*sizeof(foo) верно, оно будет работать на всех основных компиляторах сегодня.Но мне интересно, согласен ли стандарт.

1 Ответ

0 голосов
/ 08 июня 2018

Во-первых, это не тип наказания.reinterpret_cast, который вы делаете, является просто переписанным способом &result.data().foo_.Тип punning - это доступ к объекту одного типа через указатель / ссылку на другой тип.Вы обращаетесь к подобъекту другого типа.

Во-вторых, это не работает. Арифметика указателей основана на наличии массива (для целей арифметики указателей отдельный объект действует как массив из 1 элемента).И vector<T> определяется fiat для получения массива T с.Но массив T не эквивалентен массиву некоторого подобъекта T, даже если этот подобъект имеет тот же размер, что и T, а T - стандартная компоновка.

Следовательно, еслиget_foos выполняет арифметику указателей для данного массива foo s, то есть UB.О, конечно, это почти наверняка будет работать .Но ответ языка - UB.

...