Доступ к переменной-члену через родительский класс и смещение
Я поставил тег language lawyer
Хотя у меня есть ощущение, что это не с той стороны стандартной границы. Я не видел разговора именно по этому вопросу, но у меня был на работе, поэтому я хотел бы иметь определенную уверенность в этом.
Проблема заключается в доступе (потенциально) к частным полям виртуальных базовых классов. Скажем, я вычисляю смещение частного поля класса, а затем использую это смещение вне класса для доступа (чтения / записи) к переменной-члену в этом месте.
Я видел, что есть расширение для GCC и Clang offsetof
(этот условно определен в C++17, что это значит?), и его использование эквивалентно некоторой арифметике указателей, например:
#include <iostream>
class A
{
int a{};
public:
int aa{};
static ptrdiff_t getAOffset()
{
A instance;
return reinterpret_cast<ptrdiff_t>(static_cast<const void*>(&instance)) - reinterpret_cast<ptrdiff_t>(static_cast<const void*>(&(instance.a)));
//return offsetof(A, a); // "same" as this call to offset
}
int get() const
{
return a;
}
};
class B: public virtual A
{
};
void update_field(char* pointer, ptrdiff_t offset, int value)
{
int* field = reinterpret_cast<int*>(pointer + offset);
*field = value;
}
void modify_a(B& instance)
{
update_field(reinterpret_cast<char*>(dynamic_cast<A*>(&instance)), A::getAOffset(), 1);
}
int main()
{
B instance;
std::cout << instance.get() << std::endl;
modify_a(instance);
std::cout << instance.get() << std::endl;
}
Я также сделал колирус (педантичный), который не жалуется, но все же... https://coliru.stacked-crooked.com/a/faecd0b248eff651
Есть ли что-то в стандарте, что разрешает это, или это в неопределенном поведении земли? Рад также видеть, есть ли разница между стандартами.