2014-02-05 5 views
3

От стандарта C++:Использование offsetof для шаблонных классов

Класс стандартного макета класс, который:

- не имеет нестатических элементов данных класса типа нестандартного макета (или массив таких типов) или ссылки,

- не имеет виртуальные функции (10.3) и никаких виртуальных базовых классов (10.1),

- имеет один и тот же контроль доступа (пункт 11) для всех не-го элементы данных АИКТА, - не имеют нестандартной компоновку базовых классов,

- либо не имеют не-статические элементов данных в наиболее производном классе и не более одного базового класса с не-статическими элементами данных, или имеют нет базы классы с не-статические элементы данных, и

- не имеет базовых классов одного и того же типа, что и первый не-статические данные член

макрос offsetof (тип, член-целеуказатель) принимает ограниченный набор аргументов типа в этом международном стандарте. Если тип не является класс стандартного макета (пункт 9), результаты не определены

Учитывая эти заявления, есть ли безопасный способ использования offsetof для членов, которые зависят от параметров шаблона? Если нет, как мне получить смещение члена в шаблонных классах? Что может быть небезопасным при использовании чего-то типа:

//MS Visual Studio 2013 definition 
#define offsetof(s,m) (size_t)&reinterpret_cast<const volatile char&>((((s *)0)->m)) 

по нестандартным классам макетов?

После образца, где не SAFE в соответствии со стандартом:

#include <cstddef> 
#include <iostream> 

template<typename T> 
struct Test 
{ 
    int  a; 
    T  b; 
}; 

struct NonStdLayout 
{ 
    virtual void f(){}; 
}; 

int main() 
{ 
    std::cout << offsetof(Test<int>, b) << std::endl; 
    std::cout << offsetof(Test<NonStdLayout>, b) << std::endl; 
    return 0; 
} 

ответ

1

offsetof не может быть использован на классах нестандартной верстки просто потому, что их расположение в памяти неизвестно. Например, в стандарте не указывается, как реализованы виртуальные функции-члены. Один из распространенных способов сделать это - добавить указатель на vtable в качестве первого элемента данных класса, но это не единственный способ.

Что касается вашего определения offsetof: нет никакой гарантии, что нулевой указатель преобразуется в 0 через reinterpret_cast (или через C-стиль актер), ни есть ли семантика, указанная для других значений указателей, поданных в целые числа.

So Если вы знаете, что ваше определение имеет смысл в базовой схеме адресации, используемой вашим компилятором для вашей платформы, оно может работать. Но это , если вы должны знать.

1

Ответ заключается в том, что совершенно безопасно использовать offsetof в шаблонах. Таким образом, никакого вреда не будет. Однако, если вы решите это сделать, вы наложите ограничение на тип параметра для шаблона. Он будет корректно работать для стандартных классов макета, и в принципе, по крайней мере, компилятор должен сказать вам, когда параметр имеет тип, для которого он не будет работать.

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

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

 Смежные вопросы

  • Нет связанных вопросов^_^