Обратите внимание, что код, который вы рассматриваете, проверяет тип возврата явного выражения вызова деструктора. Это не придает никакого значения типу возврата самого деструктора.
Явное выражение вызова деструктора может быть, а может и не быть выражением вызова функции (это если тип является классом с деструктором, это не так, если тип имеет тривиальное уничтожение, потому что это неклассный тип). Вызовы функций описаны в [expr.call]
, который имеет следующее специальное правило для явных вызовов деструкторов:
Если постфиксное выражение обозначает деструктор, тип выражения вызова функции будет void
; в противном случае тип выражения вызова функции является типом возврата статически выбранной функции (т. е.
игнорируя ключевое слово virtual
), даже если тип фактически вызванной функции отличается. Этот возвращаемый тип должен быть типом объекта, ссылочным типом или cv
void
.
Где это не применимо, это вызовы псевдо-деструктора, описанные в [expr.pseudo]
( Вызов псевдо-деструктора ), который гласит следующее:
Использование псевдо-деструктора-имени после оператора .
или стрелки ->
представляет деструктор для неклассового типа, обозначаемого type-name или спецификатор decltype . Результат должен использоваться только в качестве операнда для оператора вызова функции ()
, а результат такого вызова имеет тип void
. Единственный эффект - это оценка постфиксного выражения перед точкой или стрелкой.
Как видите, ни в одном из случаев не достигается предложение, которое делает тип возвращаемого значения функции и тип выражения вызова функции одинаковыми. Таким образом, выражение имеет тип void
, хотя функция (специальный член) вообще не имеет возвращаемого типа.