Подтвердить что ты не робот

Является ли std:: array <T, S> гарантированным POD, если T является POD?

В настоящее время я пишу библиотеку редактирования С++-памяти, а для API-интерфейсов чтения/записи я использую черты типов (std:: is_pod, std:: is_same) и boost:: enable_if, чтобы обеспечить 3 перегрузки:

  • Типы POD. например MyMem.Read(SomeAddress);
  • Строковые типы. например MyMem.Read > (SomeAddress); (На самом деле это не считывает строку С++, она считывает строку в стиле C и преобразует ее в строку С++.)
  • Типы векторов. например MyMem.Read > (SomeAddress, NumElem); (Это фактически не считывает вектор, скорее, он считывает массив C-стиля и преобразует его в вектор.)

Перегрузки 2 и 3 - это просто "обертки" вокруг перегрузки 1. (Так что, если вы читаете std::vector или std:: basic_string, а T не POD, это не сработает, как и должно быть.)

Недавно я хотел использовать std:: array для кучи чтения и записи, потому что знал размер данных, которые я хотел читать и писать во время компиляции (я писал обертку вокруг формата файла PE).

Я написал код для использования std:: array, а затем решил добавить еще одну перегрузку для обнаружения и обработки типов std:: array, но я случайно попал в компиляцию и, к моему удивлению, сработает!

В настоящее время я использую MSVC 10, и получается, что для std:: array, если T - POD, std:: array - POD. (Это означает, что я могу просто использовать перегрузку 1, и она работает.)

Мой вопрос заключается в том, гарантируется ли это стандартом С++ или до реализации.

Я знаю, что могу сам проверить этот стандарт, но я не доверяю себе, насколько я доверяю некоторым юристам на этом сайте, поэтому я решил, что лучше всего получить "второе мнение".;)

Спасибо

P.S. Код доступен здесь (это только заголовок): http://code.google.com/p/hadesmem/source/browse/trunk/HadesMem-v2/Hades-Memory/Hades-Memory/MemoryMgr.h#86

4b9b3361

Ответ 1

§23.3.1:

Массив - это агрегат (8.5.1), который может быть инициализирован синтаксисом array a<T, N> = { initializer-list };где список-инициализатор представляет собой список, разделенный запятыми, до N элементов, типы которых можно конвертировать в T.

В С++ 03 POD был определен в терминах aggregate: class, где каждый подобъект является родным или агрегатом является POD. Таким образом, благодаря обратной совместимости С++ 0x std::array является POD.

Или, чтобы быть анальным, можно сравнить пулевые точки § 9/5 (определяющие тривиальный класс) 9/6 (определение стандартного макета) и 9/9 (объединение предыдущих требований в POD) с параметрами 8.5.1/1, который определяет агрегаты.

8.5.1

Агрегат - это массив или класс (раздел 9) без конструкторов, предоставляемых пользователем (12.1), без инициализаторов с привязкой или равными для нестатических членов данных (9.2), без частных или защищенных нестатических (раздел 11), нет базовых классов (раздел 10) и нет виртуальных функций (10.3).

В действительности требования в разделе 9 охватывают array, пока его тип элемента также является POD, и реализация не объявляет operator= или move внутри array в дополнение к спецификациям.

Чтобы быть действительно анальным, 17.5.2.2 говорит

  • В целях изложения в статьях 18-30 и приложении D не описываются конструкторы копирования/перемещения, операторы присваивания или (не виртуальные) деструкторы с той же очевидной семантикой, что и те, которые могут быть сгенерированы по умолчанию (12.1, 12.4, 12.8).
  • Неизвестно, реализует ли реализация явные определения для таких значений функций-членов или для виртуальных деструкторов, которые могут быть сгенерированы по умолчанию.

Примечание в псевдокоде для template class array есть

// No explicit construct/copy/destroy for aggregate type

Включает ли construct/copy/destroy operator= (присвоение) или move? Вероятно, это должно произойти, но я не думаю, что, строго говоря, оно делает.

Обратите внимание, что это "влияет" не только на POD-ness, но и на тривиальную копируемость, о чем упоминает Йоханнес.

Ответ 2

По определению POD:

9 Классы

9 Структура POD - это класс, который является как тривиальным классом, так и классом стандартного макета, и не имеет нестатических членов данных типа non-POD struct, non-POD union ( или массив таких типов). Аналогично, объединение POD представляет собой объединение, которое является тривиальным классом и стандартным классом макета, и не имеет нестатических членов данных типа non-POD struct, non-POD union (или массив таких типов). Класс POD - это класс, который представляет собой либо структуру POD, либо объединение POD.

[Акцент мой]

std::array удовлетворяет всем требованиям, предъявляемым к тривиальному шаблону класса стандартного макета. Поэтому ответ на ваш вопрос - да.

Ответ 3

Potatoswatter обнаружил ошибку в моих выводах. С++ явно позволяет реализации явно определять оператор присваивания "с той же очевидной семантикой". Это сделает его не подлежащим тривиальному копированию. Создание сообщества wiki...


Мне кажется, что вы не хотите тестировать PODnes, но против тривиально скопируемых, что намного менее ограничивает. Потому что это типы ограничений С++ 0x, которые можно использовать с memcpy и друзьями.

И хотя я не думаю, что есть какие-либо гарантии в отношении PODness std::array , есть гарантии о тривиальной копируемости, как показано ниже (если у меня нет ошибки в выводы). Как известно, std::array является агрегатом, а агрегаты

Агрегат - это массив или класс (раздел 9) без конструкторов, предоставляемых пользователем (12.1), без скобок или равно- инициализаторы для нестатических членов данных (9.2), нет частных или защищенных нестатических данных (раздел 11), нет базовых классов (раздел 10) и нет виртуальных функций (10.3).

Хотя тривиальная копируемость определена для класса с классом, который

  • не имеет нетривиальных конструкторов копирования (12.8),
  • не имеет нетривиальных конструкторов перемещения (12.8),
  • не имеет нетривиальных операторов присваивания копий (13.5.3, 12.8),
  • не имеет нетривиальных операторов присваивания перемещения (13.5.3, 12.8) и
  • имеет тривиальный деструктор (12.4).

std::array не имеет деструктора (как сказано в определении std::array). По-видимому, это не вытекает из определения агрегатных классов, хотя комментарий в определении класса std::array утверждает, что.

Остальные 4 требования следуют из-за отсутствия оснований, виртуальных функций и предоставленных пользователем версий для этих 4 специальных функций-членов для агрегатов.Забастовкa >