#cpp #шаблоны_с++ #cpp17
#includetemplate struct A { static_assert(!std::is_same_v ); }; template struct B { void foo() { A {}; } }; int main() { } Почему эта программа компилируется gcc и msvc (1 и 2), но не компилируется clang (3)? Должна ли она компилироваться в соответствии со стандартом?
Ответы
Ответ 1
Формально - Clang неправ, код должен компилироваться. Так как foo нигде не используется, она не должна инстантинироваться. Следовательно, Aтоже не должен инстантинироваться, и static_assert не должен срабатывать. Но вообще, по духу стандарта код должен быть ill-formed, no diagnostic required (что означало бы, что код невалиден, и что все три компилятора соответствуют стандарту) из-за вот этого раздела: [temp.res]/8.1 8 The validity of a template may be checked prior to any instantiation. [ Note: Knowing which names are type names allows the syntax of every template to be checked in this way. — end note ] The program is ill-formed, no diagnostic required, if: (8.1) — no valid specialization can be generated for a template or a substatement of a constexpr if statement within a template and the template is not instantiated, or ... (emphasis mine) То есть если код в шаблоне некорректен для абсолютно всех возможных наборов шаблонных аргументов, то программа невалидна (но сообщение об ошибке не гарантируется). foo невалидна для всех T, но так как сама foo() - не шаблон, к ней этот раздел не применяется. Почему я говорю "по духу стандарта"? Существует: CWG issue 1253: Generic non-template members Section: 17.8 [temp.spec] Status: drafting Submitter: Nikolay Ivchenkov Date: 2011-03-06 Many statements in the Standard apply only to templates, for example, 17.7 [temp.res] paragraph 8: If no valid specialization can be generated for a template definition, and that template is not instantiated, the template definition is ill-formed, no diagnostic required. This clearly should apply to non-template member functions of class templates, not just to templates per se. Terminology should be established to refer to these generic entities that are not actually templates. (Спасибо @StoryTeller.) Которая как раз утверждает, что разделы вроде [temp.res]/8.1 должны применяться не только к шаблонам, но и нешаблонным членам шаблонных классов и т. п. Судя по Status: drafting Комитет согласен, что это нужно исправить, но с конкретными изменениями в текст стандарта по этой теме они пока не определились. Ответ 2
Нет, не должна. В таком случае (определение структуры) нужна обязательная инстанциация. Однако стандарт разрешает не диагностировать подобную ошибку, если вызова не произошло (т.к. это потенциально замедляет компиляцию). Так что все правы, но clang более строг, как обычно.
Комментариев нет:
Отправить комментарий