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

Что не так с этим использованием offsetof?

Я компилирую код С++ в MinGW GCC 4.4.0 и получаю предупреждения со следующей формой...

warning: invalid access to non-static data member '<membername>'  of NULL object
warning: (perhaps the 'offsetof' macro was used incorrectly)

Эта проблема кажется знакомой - что-то, о чем я пытался решить раньше, и провалился, думаю, но недавно. Код строит отлично в Visual С++, но я не создал этот конкретный код в последнее время в любом другом компиляторе.

Код проблемы - это следующий шаблон...

template<typename T>
class c_Align_Of
{
  private:
    struct c_Test
    {
      char m_Char;
      T    m_Test;
    };
  public:
    enum { e_Align = offsetof (c_Test, m_Test) };
};

Очевидно, я могу использовать некоторую условную компиляцию для использования для этого функций, связанных с компилятором, и я считаю, что С++ 0x (наконец) сделает его избыточным. Но в любом случае я не вижу ничего плохого в этом использовании offsetof.

Очень педантично, возможно, что, поскольку типы параметров T иногда не являются POD, поэтому классы GCC c_Test как не-POD и жалуются (и жалуются и жалуются), я получаю почти 800 строк этих предупреждений).

Это непослушная строгая формулировка стандарта, так как не-POD-типы могут сломаться offsetof. Однако такой вид не-POD не должен быть проблемой на практике - c_Test не будет иметь виртуальную таблицу, и для определения смещения m_Test не требуется обход времени выполнения.

Кроме того, даже если c_Test имела виртуальную таблицу, GCC реализует макрос offsetof с использованием встроенного объекта, который всегда оценивается во время компиляции на основе статического расположения этого конкретного типа. Предоставление инструмента, а затем нытье (извините, предупреждение) каждый раз, когда он используется, просто кажется глупым.

Кроме того, я не единственный человек, который здесь делает такие вещи...

Отвечайте на вопрос, связанный с легитимным использованием офсетного вопроса

Я помню, что проблема с offsetof для такого рода причин, но я не думаю, что проблема была в этом шаблоне.

Любые идеи?

4b9b3361

Ответ 1

Упс...

Проблема заключается в том, что структура c_Test не является POD из-за того, что тип T не является POD. Вот цитата из руководства GCC...

-Wno-invalid-offsetof (только С++ и Objective-C ++)

Подавлять предупреждения от применения 'Offsetof macro для не-POD-типа.

В соответствии с ISO ISO С++ 1998 года стандарт, применяя "смещение к не-POD-тип undefined. В существующих Однако реализации С++, 'Offsetof обычно дает значимые результаты, даже если они применяются к определенным виды не-POD-типов. (Например, простая" структура, которая не может быть POD типа только в силу наличия конструктор.) Этот флаг предназначен для пользователей кто знает, что они пишут нелегальный код и намеренно выбранный, чтобы игнорировать предупреждая об этом.

Ограничения на 'offsetof могут быть смягченный в будущей версии С++ стандарт.

Моя проблема в том, что почти все мои T-типы имеют конструкторы и поэтому классифицируются как не-POD. Я проигнорировал этот момент как неактуальный ранее - и, конечно же, он должен быть неактуальным для смещения в принципе. Проблема в том, что стандарт С++ использует одну классификацию POD и non-POD, хотя существует несколько различных способов быть не-POD, и компилятор правильно предупреждает о нестандартном использовании по умолчанию.

Мое решение на данный момент будет вариантом выше, чтобы подавить предупреждение - теперь мне просто нужно выяснить, как сказать cmake, чтобы использовать его.

Ответ 2

Ну наивная интерпретация этой конкретной ошибки заключается в том, чтобы взять ее по номинальной стоимости: Вы получаете доступ к частному полю внутри перечисления. Но предположительно, перечисления статичны по определению (я полагаю, именно поэтому работа с константами enum возможна, во-первых, это по существу int-константы с причудливым именем).