Статическое утверждение в специализации шаблона не выполняется, даже если он не создан

Следующий код компилируется нормально:

#include <type_traits>

template <typename T> struct dependent_true : std::true_type { };
template <typename T> struct dependent_false : std::false_type { };

template <bool B = false>
class X { static_assert(dependent_false<X>::value); };

template <>
class X<true> { static_assert(dependent_true<X>::value); };

int main() {
   X<true> x;
}

То есть static_assert в первичном шаблоне не оценивается. Напротив, если я переключусь на:

template <bool B = false>
class X { static_assert(dependent_true<X>::value); };

template <>
class X<true> { static_assert(dependent_false<X>::value); };

int main() {
    X<false> x;
}

Затем статическое утверждение в специализации шаблона не выполняется, даже если оно не создано. Мне просто интересно, почему. Я наблюдал такое поведение с GCC 8 и Clang 6 (-std=c++17).

Живая демонстрация: https://wandbox.org/permlink/MOWNLnGMgmuDA2Ht

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
0
601
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

То же самое и с if constexpr, вы также не можете использовать static_assert с выражениями, заведомо ложными, даже если часть, где находится этот static_assert, всегда отбрасывается.

Ответ принят как подходящий

template <> class X<true> {/* ... */}; - больше не шаблон.

[temp.expl.spec]/5

A member of an explicitly specialized class is not implicitly instantiated from the member declaration of the class template; instead, the member of the class template specialization shall itself be explicitly defined if its definition is required. In this case, the definition of the class template explicit specialization shall be in scope at the point at which the member is defined. The definition of an explicitly specialized class is unrelated to the definition of a generated specialization. That is, its members need not have the same names, types, etc. as the members of a generated specialization. Members of an explicitly specialized class template are defined in the same manner as members of normal classes, and not using the template<> syntax. The same is true when defining a member of an explicitly specialized member class. However, template<> is used in defining a member of an explicitly specialized member class template that is specialized as a class template.

Специализация такая же, как у обычного класса. Это не шаблон и ни от чего не зависит. Следовательно, dependent_false<X>::value - это просто постоянное выражение, которое немедленно принимает ложное значение. Таким образом, статическое утверждение запускается немедленно.

Другие вопросы по теме