Я использовал шаблон ниже для привязки данных к произвольным объектам. Каждый объект T
живет в Wrapper<T>
, а дополнительные данные доступны с фиксированным смещением от T
.Безопасный доступ к родительскому классу путем литья первого поля
template <class T>
struct Wrapper
{
T core;
int id;
template <class ...Args>
Wrapper(int id, Args&&... args)
: id(id)
, core(std::forward<Args>(args)...) { }
};
template <class T>
Wrapper<T>& getWrapper(T& core)
{
return reinterpret_cast<Wrapper<T>&>(core);
}
void process(std::string& s)
{
std::cout << "'" << s << "' - id "
<< getWrapper(s).id << "\n";
}
int main()
{
auto *wrapper = new Wrapper<std::string>(188, "Costa Rica");
process(wrapper->core);
}
Если мое понимание стандарта является правильным, это портативное при условии T
имеет стандартный макет.
Мой вопрос - GCC конкретный. По объектной модели GCC я могу предположить, что это будет работать и тогда, когда T
не является стандартным макетом?
Даже если T имеет таблицу vtable, почему это повлияет на reinterpret_cast? Важно то, что Wrapper имеет «стандартную» компоновку (нет vtable), независимо от макета T. Заметьте, я также предполагаю, что адрес T совпадает с его указателем vtable. –