Является ли неопределенным поведение вызывать виртуальные функции члена объединения с общим базовым классом в качестве другого члена? - PullRequest
6 голосов
/ 10 июня 2019

В частности, я хотел бы иметь возможность использовать полиморфизм без выделения кучи во встроенном контексте (то есть без динамического выделения).Похоже, меня беспокоит то, что доступ к члену base, в то время как x или y являются «активными» в объединении, кажется, является примером наказания типов, даже если они имеют один и тот же начальный заголовок (и структуру vtable).).Будет ли приведенный ниже код рассматриваться как определенное поведение?

#include <iostream>
#include <new>

using namespace std;

struct Base {
    virtual const char *foo() { return "base"; }
};

struct X: public Base {
    const char *foo() override { return "d1"; }
};

struct Y: public Base {
    const char *foo() override { return "d2"; }
};

union DerivedAny {
    DerivedAny() {}
    Base& get() { return *launder(&b); }
    Base b = {};
    X x;
    Y y;
};

DerivedAny objs[3];

int main() {
    new (&objs[1].x) X;
    new (&objs[2].y) Y;
    cout << objs[0].get().foo() << endl;
    cout << objs[1].get().foo() << endl;
    cout << objs[2].get().foo() << endl;
}

Я скомпилировал его как с GCC, так и с Clang, и они должны отображать ожидаемый результат в обоих случаях:

base
d1
d2
...