#c
#c
Вопрос:
У меня есть структура данных, в которой хранятся POD-структуры (каждый экземпляр хранит только один тип, поскольку это в основном массив определенной POD-структуры). Иногда другой разработчик изменяет одну из этих структур, добавляя или модифицируя тип данных. Если добавляется элемент, отличный от POD, например, std::string, структура данных разрушается во время выполнения, поскольку изменяется модель памяти. Есть ли какой-нибудь способ определить, совместим ли класс или структура с POD, используя определения компилятора или вызов во время выполнения (чтобы избежать этой проблемы с сопровождением)? Я использую g (GCC) 4.2.4.
Комментарии:
1. Обычным подходом к решению этой проблемы является проверка кода.
2. @unapersson: При проверке кода в этом случае часто не удается обнаружить проблему, особенно в больших кодовых базах. Поддержка компилятора — лучший подход.
3. @John Нет. Обзоры кода — лучший способ обнаружить почти все семантические (а не синтаксические) проблемы с кодом.
4. @unapersson: В данном случае я не могу согласиться. Во всех случаях, когда компилятор может вызвать ошибку, он будет делать это всегда , в то время как проверки кода могут пропускать некоторые случаи. Кто-то может использовать тип
X
в контейнере, и этот тип может содержать другой типY
, который, в свою очередь, содержитZ
… которая может быть изменена на не-pod. Поскольку типZ
никогда не используется непосредственно в контейнере, источник проблемы и сама проблема разделены, и во многих случаях она не будет обнаружена. Независимо от того, насколько далеко продвинуто определениеZ
, компилятор может обнаружить это намного раньше, чем любая проверка.5. @unapersson: Мое утверждение основано на опыте. Я участвовал во многих проектах с несколькими MLOC объектами, которые могли бы сломаться, если бы их изменили на не-POD, и при проверке кода иногда не удавалось обнаружить дефект. Когда мы разработали инструменты времени компиляции, которые прерывали компиляцию при изменении этих параметров, частота обнаружения дефектов немедленно достигла 100%. Как может проверка кода когда-либо быть лучше этого? Не поймите меня неправильно, обзоры кода хороши по многим причинам — но они не являются конечным результатом.
Ответ №1:
Во время выполнения, вероятно, нет, но во время компиляции вы можете использовать is_pod
trait либо из стандартной библиотеки C 0x, либо Boost.Признаки типов.
static_assert(std::is_pod<YourStruct>::value);
Комментарии:
1. В C 03 это только половина решения. Вам придется вручную специализировать шаблон для ваших собственных типов, что вернет вас к исходной точке. Кто-то где-то меняет тип, но
is_pod<T>::value
все равно выдает true, поэтому более поздний вариантstatic_assert
благополучно проходит. Это лучше, чем ничего, но вы должны быть осторожны, чтобы это не привело к ложному чувству безопасности.2. @DennisZickeoose: Зависит от компилятора. MSVC (по крайней мере, > = 2005, возможно, старше), GCC > = 4.3 (Я думаю) и некоторые другие имеют встроенные функции, которые
is_pod
используют. Итак, если вы используете древний или иным образом неспособный компилятор, тогда да, это может быть не очень хорошим решением.3. И поскольку OP использует GCC4.2, это довольно важное различие.
4. @DennisZickeoose: Ах, точно. Что ж, есть простое решение этой проблемы, не используйте древние и неподдерживаемые компиляторы. 😉 Я бы все же сказал, что is_pod — лучший способ, даже если для этого требуется обновление компилятора.
5. Это хорошая информация — спасибо за ответ. К сожалению, на данный момент я не могу переключать компиляторы — поверьте мне, я бы хотел, чтобы я мог.
Ответ №2:
Вероятно, вы можете использовать библиотеку boost type_traits и, в частности, boost::is_pod<T>::value
в статическом assert .
Ответ №3:
Если у вас нет boost или C 0x, то, возможно, вы можете использовать какой-то факт, подобный тому, что C не позволяет использовать не-POD в качестве члена union.
Комментарии:
1. он написан на несовершенном c : D