Как явно вызвать деструктор для элемента элемента с шаблоном - PullRequest
0 голосов
/ 09 января 2019

Следующий код (вставьте в Godbolt, если хотите) компилирует

struct array {
    ~array();
};

struct node {
    array children;
};

void foo(node* bar) {
    bar->children.~array();
}

Но если я использую шаблон, компилятор получает синтаксическую ошибку, когда я явно ссылаюсь на тип шаблона. Почему и есть ли рабочее решение?

 #include <vector>
 struct node {
     std::vector<node> children;
 };

 void foo(node* bar) {
     bar->children.~std::vector<node>();
 }

Ответы [ 3 ]

0 голосов
/ 09 января 2019

Согласно [class.dtor] / 14 :

При явном вызове деструктора деструктор задается как ~, за которым следует имя-типа или decltype-спецификатор , который обозначает тип класса деструктора.

Так что уберите std:: в явном вызове. Однако явный вызов деструктора требуется только в определенных случаях, например при использовании placement new для выделения памяти. Смотрите этот FAQ ответ .

0 голосов
/ 09 января 2019

Начиная с C ++ 17 , вы можете использовать std::destroy_at:

std::destroy_at(&bar->children);

До C ++ 17 такую ​​функцию можно легко реализовать вручную (разумеется, вне пространства имен std) как:

template<class T>
void destroy_at(T* p) { p->~T(); }

Использование ИМХО намного приятнее, чем явный вызов деструктора, что вызывает проблемы с пространствами имен. См., Например, Как явным образом вызвать деструктор для пространства имен? .

0 голосов
/ 09 января 2019

Clang более полезен с сообщением об ошибке: `

 <source>:7:20: error: '~' in destructor name should be after nested name specifier
 bar->children.~std::vector<node>();`

Так что в основном вам нужно полагаться на ADL (я не гуру, поэтому, возможно, это неправильное название для материала, который вы используете, чтобы заставить его работать :)) здесь, и позвоните: bar->children.~vector<node>();

...