Должно ли быть подтверждено утверждение c в приведенном ниже коде?
#include <type_traits>
using namespace std;
struct S { int i; };
using CS = const S;
static_assert(is_same_v<decltype((CS::i)), decltype((S::i))>);
Clang и MSV C хорошо с этим, G CC считает, что утверждение срабатывает, потому что обозначенный тип decltype((CS::i))
- const int&
, а тип, обозначенный decltype((S::i))
- int&
: https://godbolt.org/z/5MqPX_. ( UPD: , как указано в комментариях, static_assert(is_same_v<decltype(CS::i), decltype(S::i)>);
принимается всеми тремя компиляторами https://godbolt.org/z/V5y-tD, но меня интересует формулировка, которая гарантирует это).
[basi c .type.qualifier] / 1, кажется, только гарантирует, что T
и const T
имеют одинаковое представление и выравнивание объектов, но не то, что члены const T
имеют одинаковое cv -квалификация в качестве соответствующих членов T
.
Черт, если режим go 100% pedanti c: я даже не думаю, что Стандарт требует, чтобы поиск в const T
нашел члена с именем N
, если T
имеет такой член. const T
может использовать c_N
вместо N
и имеет те же требования к представлению объекта и выравниванию, что и T
(при условии, что c_N
имеет тип const decltype(T::N)
). Я не нахожу слово «версия» в [basi c .type.qualifier] / 1, чтобы иметь какое-либо нормативное значение / обязательство.
INB4 вы указываете мне на C ++ 11 / C ++ 14 / C ++ 17's [class.name] / 5, говорящее
Если typedef-name , который называет cv-квалифицированный тип класса, используется, где class -name требуется, квалификаторы cv игнорируются.
спецификатор вложенного имени не требует имя-класса ( грамматика допускает как имя-класса , так и имя-типа-определения ). [class.derived] base-clause (→ base-specier-list → base-спецификатор → class-or-decltype ) делает (грамматика не позволяет typedef-name ). В любом случае, приведенное выше предложение было удалено в C ++ 20 P1131R2 , и формулировка о игнорировании cv-квалификаторов была помещена в [class.derived], единственное место, где оно применяется (в списке базовых классы в определении класса).