Расположение полей класса в памяти

Имеется вот такой класс:

template <typename Type>
class Vector
{
public:
    Type x, y, z;
};

Для удобства я добавил в него оперетор досутпа по индексу. Реализовал так:

template <typename Type>
class Vector
{
public:
    Type& operator[] (size_t index)
    {
        switch (index)
        {
            case 0: return x;
            case 1: return y;
            case 2: return z;
        }
        return z;
    }
public:
    Type x, y, z;
};

Получилось громоздко. Позже мне пришло в голову написать такую версию оперетора:

template <typename Type>
Type& Vector<Type>::operator[] (size_t index)
{
    return reinterpret_cast<Type*>(this)[index];
}

Будет ли последняя версия опрератора на разных платформах работать одинаково? При условии что:

  1. Тип у всех полей класса одинаковый.
  2. У всех полей одинаковый модификатор доступа.

Ответы (2 шт):

Автор решения: Stanislav Volodarskiy

Если изменить интерфейс, можно обойтись без сомнительных приведений. Вы готовы писать v.x() = 42; ?

template <typename Type>
class Vector {
public:
    Type& operator[](int i) {
        return data[i];
    }
    Type& x() { return data[0]; }
    Type& y() { return data[1]; }
    Type& z() { return data[2]; }

private:
    Type data[3];
};
→ Ссылка
Автор решения: Harry

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

Могут сыграть свою роль всякие выравнивания и тому подобные тонкости.

Но какой смысл обращаться к набору данных как к элементам массива, но при этом не сделать его массивом? Если животное на 4 лапах, лает, как собака, и кусается как собака - то это таки собака! Делайте массив.

Только в отличие от Stanislav Volodarskiy я бы - если вам дорого как память обращение через поля x, y, z - делал через ссылки:

template <typename Type>
class Vector {
public:
    Type& operator[](int i) { return data[i]; }
    const Type& operator[](int i) const { return data[i]; }
public:
    Type &x = data[0], &y = data[1], &z = data[2];

private:
    Type data[3];
};

Тогда обращение к данным ничем не отличается от вашего: https://ideone.com/W0y5M5

→ Ссылка