Почему нетривиальный член требует определения конструктора для анонимного объединения в том же классе - PullRequest
2 голосов
/ 22 марта 2019

В следующем коде (https://wandbox.org/permlink/j9tN0hQzINa3W7cl)

#include <iostream>
#include <memory>

using std::cout;
using std::endl;

class A {
public:
    A() {
        cout << "A::A()" << endl;
    }
    ~A() {
        cout << "A::~A()" << endl;
    }
};

class B {
public:
    ~B() {}

    void set() {
        new (&a_) A{};
    }

    void destroy() {
        a_.~A();
    }

    union {
        A a_;
    };
    A a2_{}; // (1)
};

int main() {
    auto b = B{};
}

Инвариант в приведенном выше коде заключается в том, что посредством создания и уничтожения экземпляра типа B, если элемент в варианте установлен, кто-то вызовет destroy (), чтобы уничтожить элемент в объединении.

Почему наличие (1) требует явного определения деструктора анонимного объединения в B? При компиляции компоновщик выдает ошибку с кодом

Undefined symbols for architecture x86_64:
  "B::'unnamed'::~()",

Это ошибка в Clang? Этот код прекрасно компилируется с gcc (https://wandbox.org/permlink/QvdJNWyrtG8gf9EE)

1 Ответ

0 голосов
/ 22 марта 2019

Я не могу воспроизвести точно ту проблему, которую вы описываете.Присутствует ли строка, помеченная вами // (1), или нет, не влияет на то, будет ли компилятор принимать код или нет в любом из моих тестов.Кроме того, я получаю не ошибку компоновщика, а ошибку компилятора, отмечая, что деструктор определен как удаленный.

Попробуйте это здесь

При этом,это кажется ошибкой в ​​Clang.На основе [class.dtor] \ 9 деструктор B должен не вызывать деструктор варианта члена a_

...