GCC 9.1 возвращает void & в качестве типа результата для явного вызова деструктора.Это ошибка? - PullRequest
21 голосов
/ 23 мая 2019

Я пытаюсь заставить эту проверку определенного класса работать, что основано на том факте, что decltype(std::declval<Foo>().~Foo()) равно void, если Foo имеет деструктор (который он имеетесли он определен…) и неправильно сформирован в противном случае, вызывая SFINAE в этом случае.

Однако я не могу заставить код работать с GCC 9.1, и это потому, что GCC 9.1, кажется, считает, чтовведите значение void & , если деструктор по умолчанию , рассмотрите этот пример:

#include <type_traits>

class Foo {
public:
// With this, the DestructorReturnType below becomes "void"
//    ~Foo () {} 
};

// … unless I specify the user-defined destructor above, in which case it is "void"
using DestructorReturnType = decltype(std::declval<Foo>().~Foo());

template<class T>
class TD;

// Says: aggregate 'TD<void&> t' has incomplete type and cannot be defined
TD<DestructorReturnType> t;

(доступно на https://gcc.godbolt.org/z/K1TjOP)

Если я пользователь-определить пустой деструктор, тип возвращается к void.Также, если я вернусь к GCC 8.x.

Стандарт C ++ 17 в [expr.call] гласит:

Если выражение postfix обозначает деструктор,тип выражения вызова функции void;[…]

Из-за всего этого я подозреваю, что GCC 8.x (и clang,…) верны, а GCC 9.1 просто неправильны.Или я что-то упустил?

1 Ответ

12 голосов
/ 23 мая 2019

Короче говоря: Да, это регрессия в GCC 9.1 .void& даже не является допустимым типом, поэтому что-то не так.Очевидно, что проблему можно обойти, установив параметр компилятора -fno-lifetime-dse за счет (возможно, небольшого) снижения производительности.Кроме того, версии GCC до 9.1 не затрагиваются.

Если вы найдете этот ответ, потому что вы также пытаетесь реализовать вышеприведенную проверку is-class-определенные, я думаю, что гораздо более простая форма с использованием sizeof должен быть четко определен, работать и не попадать под эту ошибку.

...