Что должно произойти, если тип выражения не зависит, но мы используем его для инициализации статической автоматической переменной? GCC и Clang отличаются по своему поведению
template<typename T>
struct A {
static inline auto x = sizeof(T{}.f);
};
A<int> a;
GCC не вызывает ошибку. Но Clang считает, что это недопустимо, потому что он создает экземпляр операнда «sizeof». GCC, кажется, пропустить этот шаг, потому что sizeof(T{}.f)
всегда имеет тип size_t
(не зависит от типа), поэтому он уже знает тип x
без конкретизации. Оба компилятора соответственно отклоняют программу, если мы ссылаемся на x
например, (void) a.x;
,
Это даже должно решить тип x
совсем? Начиная с C ++ 14, язык позволяет хранить вещи (например, функции) с «типом заполнителя» и выполнять отложенную реализацию, чтобы узнать о фактическом типе возврата позже, если я правильно помню. Это должно применить это к x
так хорошо, сохраняя x
с типом заполнителя, пока мы не обратимся к a.x
?
Какой компилятор верен в соответствии со стандартами?
РЕДАКТИРОВАТЬ
Кто-то спросил
хм, разве это не должно быть эквивалентно этому?
template<typename T> struct A { static const std::size_t x; }; template<typename T> inline constexpr std::size_t A<T>::x = sizeof(T{}.f);
Разница, и что касается меня в моем вопросе, состоит в том, что статический член данных в моем вопросе auto
, Поэтому, чтобы узнать тип x
Вам нужно знать тип инициализатора. Похоже, что Clang с готовностью создает инициализатор, чтобы получить тип. Но GCC нет, по-видимому? Я хотел бы понять, что происходит.
От [Temp.inst] / 3:
Если элемент шаблона класса или шаблон элемента не был явно создан или явно специализирован, специализация члена создается неявно, когда на специализацию ссылаются в контексте, который требует определения элемента; особенно, инициализация (и любые связанные побочные эффекты) элемента статических данных не происходит, если только сам элемент статических данных не используется таким образом, который требует определения элемента статических данных.
Просто пишу A<int> a;
не использует ни A<int>::x
таким образом, чтобы его определение существовало, поэтому его инициализация не должна происходить. GCC правильно.
Других решений пока нет …