В GCC 4–10 и Clang (все версии) этот фрагмент кода не компилируется, поскольку компилятор не может выделить память для A, поскольку A является абстрактным:
class A {
virtual void f() = 0;
};
void f(A (*)[1]) {}
Однако в GCC11+ это успешно компилируется.
Эта идиома полезна для обнаружения абстрактного класса до C++11, и Boost действительно использует ее для своей библиотеки type_traits.
Я что-то пропустил или это регресс в компиляторе?
Кстати, код не выделяет массив указателей, это один указатель на массив.
Я не понимал значения скобок вокруг (*) до сегодняшнего дня. Узнал что-то новое, спасибо. Название вопроса отредактировано, чтобы отразить это новое понимание.
@HoCheung, это все еще неправильно, указатель ничего не выделяет (кроме самого указателя).
Я не понимаю. Как бы вы это сформулировали?
@HoCheung между прочим, это происходит не только в параметре godbolt.org/z/x9zW67jnv
Название @HoCheung отредактировано, дело в том, что указатель не выделяет какой-либо массив, поэтому сказать, что это так, было бы неправильно.
P0929R2 изменил правила, чтобы больше не было неправильным упоминать тип «массив X
», где X
— тип абстрактного класса. (Конечно, такой тип никогда не может быть создан.) Это изменение было сделано, потому что было довольно глупо, что вам было разрешено упоминать тип «массив X
», когда X
неполный, только для того, чтобы позже определить X
как абстрактный класс. type и, таким образом, вызвать ошибку компиляции в точке определения.
Поскольку это изменение было одобрено как отчет о дефектах на собрании в Рапперсвиле (июнь 2018 г.), более новые версии компиляторов должны применять новые правила во всех языковых версиях (что в данном случае означает вплоть до C++98).
Я не думаю, что стандарт будет отключать такое объявление, может быть, оно просто не определено? (и то и другое правильно)