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

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

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

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

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

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

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

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

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

Спасибо

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

17 голосов | спросил RaptorFactor 9 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowThu, 09 Sep 2010 10:21:48 +0400 2010, 10:21:48

3 ответа


0

§23.3.1:

  

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

В C ++ 03 POD был определен в терминах агрегата: класс, в котором каждый подобъект является собственным или агрегатом является POD. Таким образом, благодаря обратной совместимости, C ++ 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 говорит

  
  1. В целях изложения в разделах 18–30 и Приложении D не описываются конструкторы копирования /перемещения, операторы присваивания или (не виртуальные) деструкторы с той же очевидной семантикой, что и те, которые могут генерироваться по умолчанию (12.1 12,4, 12,8).
  2.   
  3. Не указано, предоставляет ли реализация явные определения для таких сигнатур функций-членов или для виртуальных деструкторов, которые могут генерироваться по умолчанию.
  4.   

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

  

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

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

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

ответил Potatoswatter 9 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowThu, 09 Sep 2010 12:02:04 +0400 2010, 12:02:04
0

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

  

9 классов

     

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

[Акцент мой]

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

ответил dirkgently 9 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowThu, 09 Sep 2010 10:58:45 +0400 2010, 10:58:45
0

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


Мне кажется, вы не хотите тестировать против PODnes, но против тривиально копируемого , что гораздо меньше ограничений. Потому что именно так C ++ 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 специальных функций-членов для агрегатов.

ответил dirkgently 9 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowThu, 09 Sep 2010 10:58:45 +0400 2010, 10:58:45

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132