https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94545
--- Comment #2 from Thomas Mercier <thomas.mercier.jr at gmail dot com> --- I thought that might be the response. Then why does it compile? The fact that it does, and produces a result is surprising. I don't know what the standard says, but just looking at cppreference it says that specializations are provided for arithmetic types. We could have a more sane default than value initialization (https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/std/limits#L321) that produces a compilation error if it's unspecified (something like below). template<typename _Tp> struct mylimits { static constexpr _Tp max() noexcept { static_assert(sizeof(_Tp) == 0, "There is no specialization of mylimits for this type."); } }; template<> struct mylimits<bool> { static constexpr bool max() noexcept { return true; } }; // and so on... Gives you: $ g++ -std=c++17 test.cc test.cc: In instantiation of ‘static constexpr _Tp mylimits<_Tp>::max() [with _Tp = int]’: test.cc:21:34: required from here test.cc:5:5: error: static assertion failed: There is no specialization of mylimits for this type. static_assert(sizeof(_Tp) == 0, "There is no specialization of mylimits for this type.");