Я пытаюсь заставить эту проверку определенного класса работать, что основано на том факте, что 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.
Стандарт С++ 17 в [expr.call] гласит:
Если postfix-expression обозначает деструктор, тип выражения вызова функции void; [...]
Из-за всего этого я подозреваю, что GCC 8.x (и clang,...) верны, а GCC 9.1 просто неправильны. Или я что-то упустил?