ARTICLE AD BOX
[[deprecated]] might help, but for "edge cases" as template specialization, compiler behaviors might differ with that attribute.
Clang supports/warns when applied with requires:
template <typename T, int N = 8> struct C; template <typename T> struct C<T, 8> { // ... }; template <typename T, int N> requires (N != 8) struct [[deprecated]] C<T, N> { // ... }; C<bool, 5> obj_1{}; // warning as expected (with clang) C<int> obj_2; C<int, 42> obj_3; // warning as expected (with clang)That form requires to specialize whole class.
You might apply the deprecation to just some special members as constructors
template <typename T, int N = 8> struct C { C() requires(N == 8) = default; [[deprecated]]C() requires(N != 8) = default; // ... };Unfortunately, even clang doesn't warn here for deprecated destructor :/
All compilers warns for [[deprecated]] on special (non-defaulted) members inside the specialization:
template<typename T, int N = 8> struct C { [[deprecated]] C() {}; // gcc and msvc don't warn for `= default` // ... }; template<typename T> struct C<T, 8> { // ... };