Требуется ли создание экземпляра для неиспользуемого, но инициализированного статического элемента данных const int шаблC++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Anonymous
 Требуется ли создание экземпляра для неиспользуемого, но инициализированного статического элемента данных const int шабл

Сообщение Anonymous »

Если создан экземпляр шаблона класса и он содержит инициализированный

Код: Выделить всё

const int
статический элемент данных, который не используется, должен ли быть создан экземпляр этого элемента данных
(и, следовательно, его инициализатора)?
Пример:

Код: Выделить всё

template 
struct S {
static void m() {}
static const int c = sizeof(T);
};

struct A;

int main()
{
S::m();
return 0;
}
В программе не используется c, поэтому на первый взгляд можно
подумать, что она не создана, но Clang-17 и MSVC-19 это делают. похоже,
создает его экземпляр и, следовательно, отклоняет его из-за неполноты A.
Тем временем GCC-13 принимает: https://godbolt.org/z/GEcfe8a6M
Для удобства конкретная ошибка Clang:

Код: Выделить всё

:4:24: error: invalid application of 'sizeof' to an incomplete type 'A'
4 |   static const int c = sizeof(T);
|                        ^~~~~~~~~
:11:3: note: in instantiation of template class 'S' requested here
11 |   S::m();
|   ^
:7:8: note: forward declaration of 'A'
7 | struct A;
|        ^
но для ясности мой главный вопрос заключается в том, является ли исходный пример действительным для C++.
В [temp.inst] стандарта C++ 17 , в абзаце 3 говорится:

Если член шаблона класса или шаблон члена не был
явно создан или явно специализирован, специализация
члена неявно создается экземпляр, когда на специализацию
ссылаются в контексте, требующем существования определения члена
или если существование определения члена влияет на
семантику программа; в частности, инициализация (и любые
связанные с ней побочные эффекты) статического элемента данных не происходит, если
сам статический элемент данных не используется таким образом, который требует
определения статического элемента данных. элемент данных должен существовать.

Я нахожу формулировку первой части запутанной, поскольку она кажется замкнутой.
В ней говорится, что экземпляр элемента создается, если его существование влияет на семантику
программы. Но если бы его существование не влияло на семантику, то
было бы невозможно наблюдать, был ли он создан или нет! Таким образом,
было бы эквивалентно утверждению, что все члены создаются, но это,
конечно, не то, что делают реализации. (Примечание: я предполагаю, что
"создать экземпляр члена" означает "создать экземпляр его определения", в соответствии с
выводом в
Являются ли статические члены шаблона класса неявно созданными экземплярами или нет? ?.)
Тогда вторая часть, начинающаяся с «в частности», как бы
противоречит первой части. Во второй части говорится, что создание
статического элемента данных происходит только в том случае, если этот элемент используется, но, конечно,
использование - это лишь один из способов, которым его существование может повлиять на семантику. Это также
похоже, подразумевает, что в приведенном выше примере c не следует создавать
экземпляр из-за недостаточного использования.
В том же разделе , начинается абзац 7:

Считается, что наличие определения переменной или функции
влияет на семантику программы, если переменная или функция
нужна для постоянного вычисления выражения (8.6), [...]

но это, похоже, к этому не относится пример, потому что c никогда
не требуется для постоянного вычисления (опять же, он вообще не используется).
[class.static.data] абзац 3 начинается:

Если энергонезависимый невстраиваемый константный статический элемент данных имеет целочисленный
тип или перечисляемый тип, его объявление в определении класса может
укажите инициализатор скобок или равенства, в котором каждое предложение-инициализатора
, являющееся выражением-присваивания, является постоянным выражением (8.6).
[...]

Я думаю, что это правило должно применяться только в том случае, если элемент создается, поскольку
результат зависит от аргумента шаблона. Однако я подозреваю, что
это правило задействовано, потому что если я перенесу определение члена за пределы
тела класса, то все компиляторы его примут:
https://godbolt.org/z/ 9cG1nzvnq
Основываясь на чтении стандарта, я пришел к выводу, что S::c не должен
создавать экземпляры. GCC согласен, но Clang и MSVC не согласны. Что
правильно?

Подробнее здесь: https://stackoverflow.com/questions/784 ... ic-data-me
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C++»