Явный вызов деструктора int - зачем нужен псевдоним типа?

Следующая программа ...

int main()
{
    int{1}.~int();
}

не компилируется на (см. средство просмотра соответствия):

  • clang ++ магистраль с -std=c++1z

  • ствол g ++ с -std=c++1z

  • CL 19 2017


Представляем псевдоним типа для _4 _...

int main()
{
    using X = int;
    int{1}.~X();
}

... делает программу действительной на всех ранее упомянутых компиляторах без предупреждений (см. средство просмотра соответствия) .

Почему при вызове деструктора int требуется псевдоним типа? Это потому, что int не является допустимым элементом грамматики для вызова уничтожения?


person Vittorio Romeo    schedule 26.09.2017    source источник
comment
Зачем вам когда-либо вызывать деструктор int?   -  person    schedule 26.09.2017
comment
Int - это собственный тип, нужен ли для него деструктор?   -  person Girauder    schedule 26.09.2017
comment
@ manni66: это имеет смысл в общем контексте (например, реализация std::optional), но этот вопрос был создан исключительно из любопытства.   -  person Vittorio Romeo    schedule 26.09.2017
comment
Похоже, кто-то смотрел C ++ WAT.   -  person nwp    schedule 26.09.2017
comment
@nwp: Ого, я действительно присутствовал на этом выступлении в 2015 году. Это было очень весело. Этот вопрос не имеет к этому никакого отношения, он возник в результате какого-то обсуждения в моем внутреннем корпоративном чате на C ++ :)   -  person Vittorio Romeo    schedule 26.09.2017
comment
Похоже, он должен работать (см. пункт 7 здесь) ...   -  person Quentin    schedule 26.09.2017
comment
Я почти уверен, что t.~T() работает в шаблоне, заботясь об общих контекстах. Не могу сказать, что могу придумать ситуацию, в которой я хотел бы использовать int напрямую.   -  person chris    schedule 26.09.2017
comment
Почему голос против? @chris: я тоже, это в основном вопрос из любопытства юриста по языку.   -  person Vittorio Romeo    schedule 26.09.2017
comment
Я пометил как повторяющийся, потому что Коломбо прибил его в своем ответе. На самом деле вы не можете вызвать деструктор для скаляров, потому что у них его нет (см. §12.4). Этот оператор разрешен только для кода шаблона, в котором вы вызываете деструктор объекта, тип которого вам неизвестен - он устраняет необходимость написания специализации для скалярных типов. - Замечу, что для точности 12.4 следует заменить на [class.dtor].   -  person AndyG    schedule 26.09.2017


Ответы (1)


Это работает, потому что грамматика не предусмотрела встроенные типы, но предусмотрела псевдонимы:

[expr.post] / 1:

postfix-expression:
    postfix-expression . pseudo-destructor-name
    postfix-expression -> pseudo-destructor-name

pseudo-destructor-name:
    ~ type-name
    ~ decltype-specifier

И [dcl.type.simple] / 1:

type-name:
  class-name
  enum-name
  typedef-name
  simple-template-id

Вы можете себе представить, что означает каждая переменная в type-name. В данном случае [expr.pseudo] / 1 указывает что это просто void выражение:

Использование имени псевдодеструктора после точки. Оператор или стрелка -> представляет деструктор для неклассового типа, обозначенного type-name или decltype-specier. Результат должен использоваться только как операнд для вызова функции operator (), а результат такого вызова имеет тип void. Единственный эффект - это оценка постфиксного выражения перед точкой или стрелкой.

Интересно отметить, что вы должны иметь возможность делать это без псевдонима (если у вас есть именованный объект), потому что вызов псевдодеструктора также работает со спецификатором decltype:

auto a = int{1};
a.~decltype(a)();
person StoryTeller - Unslander Monica    schedule 26.09.2017
comment
Последний фрагмент не компилируется для gcc (ожидаемый идентификатор перед 'decltype'), но компилируется для clang. По вашему мнению, это ошибка / ограничение в магистрали gcc? Связанный: для конкретного случая этого примера (int) мы можем использовать (очевидный) факт, что спецификатор decltype, примененный к целочисленному литералу, дает тип int, чтобы построить int{1}.~decltype(0)();, который компилируется с clang. Более того, что характерно, int{1}.~decltype(auto)(); вылетает лязг, предлагая нам отправить отчет об ошибке. Например, пользовательский POD Foo, Foo{1}.~decltype(auto)(); не дает сбоев, но выдает ошибку. - person dfrib; 26.09.2017
comment
@dfri - сухая буква стандарта указывает, что как ошибка в GCC, да. И это должно быть исправлено, поскольку конструкция легальна. Что касается сбоя в Clang ... это такой крайний случай, я не уверен, что стоит сообщать об ошибке. - person StoryTeller - Unslander Monica; 27.09.2017
comment
Спасибо. Что касается сбоя clang, я согласен, и было бы глупо, если бы опубликовал отчет об ошибке. - person dfrib; 27.09.2017