Следующий код компилируется нормально:
#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





Даже части шаблона, не являющиеся экземплярами, должны быть действительным кодом C++. static_assert(false) делает программу некорректной. Итак, у вас есть специализация на static_assert, который на момент компиляции известен как false, и ваша программа становится плохо сформированной. У вас нет неразрешенных параметров шаблона в вашем классе, который используется в static_assert, чтобы заставить компилятор удивляться; он точно знает, что это false.
То же самое и с if constexpr, вы также не можете использовать static_assert с выражениями, заведомо ложными, даже если часть, где находится этот static_assert, всегда отбрасывается.
template <> class X<true> {/* ... */}; - больше не шаблон.
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 - это просто постоянное выражение, которое немедленно принимает ложное значение. Таким образом, статическое утверждение запускается немедленно.