Skip to content

Conversation

localspook
Copy link
Contributor

@localspook localspook commented May 24, 2025

This PR marks templates users shouldn't specialize with [[msvc::no_specializations]] or [[clang::no_specializations]], depending on the compiler.

Resolves #5179.

All citations in this PR description are to WG21-N5014.

Class Templates

[namespace.std]/2 allows class template specializations by default. Exceptions:

Specializations forbidden By paragraph
initializer_list [initializer.list.syn]/2
compare_three_way_result [cmp.result]/1
allocator_traits [allocator.traits.general]/1
coroutine_handle [coroutine.handle.general]/2
is_execution_policy [execpol.type]/3
basic_format_arg [format.arg]/2
basic_format_context [format.context]/2
basic_format_parse_context [format.parse.ctx]/2
is_clock [time.traits.is.clock]/2
generator [coro.generator.class]/4
range_adaptor_closure [range.adaptor.object]/5
variant [variant.variant.general]/4
tuple [tuple.tuple.general]/1
unary_function WG21-N4140 [depr.base]/1
binary_function WG21-N4140 [depr.base]/1

Variable Templates

[namespace.std]/3 forbids variable template specializations by default.

Specializations allowed By paragraph
format_kind [format.range.fmtkind]/3
disable_sized_sentinel_for [iterator.concept.sizedsentinel]/3
enable_borrowed_range [range.range]/6
disable_sized_range [range.sized]/3
enable_view [range.view]/7
enable_nonlocking_formatter_optimization [format.formatter.locking]/1
e_v [math.constants]/2
log2e_v [math.constants]/2
log10e_v [math.constants]/2
pi_v [math.constants]/2
inv_pi_v [math.constants]/2
inv_sqrtpi_v [math.constants]/2
ln2_v [math.constants]/2
ln10_v [math.constants]/2
sqrt2_v [math.constants]/2
sqrt3_v [math.constants]/2
inv_sqrt3_v [math.constants]/2
egamma_v [math.constants]/2
phi_v [math.constants]/2

Type Traits

[meta.rqmts]/4 forbids specializing any template in <type_traits> by default.

Specializations allowed By paragraph
common_type [meta.trans.other]/5
basic_common_reference [meta.trans.other]/7

Function Templates

Specializing function templates is forbidden, but, following the decision made in #24, this PR doesn't touch any of them (except for is_pointer_interconvertible_with_class and is_corresponding_member in <type_traits>, as specializing those has always been forbidden).

Notes

Relevant: llvm/llvm-project#118167 implemented this warning in libc++.

@localspook localspook requested a review from a team as a code owner May 24, 2025 00:57
@github-project-automation github-project-automation bot moved this to Initial Review in STL Code Reviews May 24, 2025
@localspook

This comment was marked as off-topic.

@localspook

This comment was marked as resolved.

@localspook localspook changed the title Mark templates users shouldn't specialize with _NO_SPECIALIZATIONS Mark templates users shouldn't specialize with _NO_SPECIALIZATIONS May 24, 2025
@localspook

This comment was marked as resolved.

@AlexGuteniev

This comment was marked as resolved.

@localspook

This comment was marked as resolved.

@StephanTLavavej StephanTLavavej self-assigned this May 27, 2025
@StephanTLavavej StephanTLavavej added the enhancement Something can be improved label May 27, 2025
@localspook

This comment was marked as resolved.

@localspook

This comment was marked as off-topic.

@StephanTLavavej

This comment was marked as resolved.

This comment was marked as resolved.

@StephanTLavavej
Copy link
Member

StephanTLavavej commented Sep 18, 2025

Click to expand usage example:
D:\GitHub\STL\out\x64>type meow.cpp
#include <chrono>
#include <type_traits>

template <class T>
struct Kitty {};

namespace std {
    namespace chrono {
        template <class T>
        struct is_clock<Kitty<T>> : true_type {};
    } // namespace chrono
} // namespace std

int main() {
    static_assert(std::chrono::is_clock<Kitty<int>>::value);
}
D:\GitHub\STL\out\x64>cl /EHsc /nologo /W1 /std:c++latest meow.cpp
meow.cpp
meow.cpp(10): warning C5285: cannot declare a specialization for 'std::chrono::is_clock': Specializing this standard library template is forbidden by N5014 [time.traits.is.clock]/2
D:\GitHub\STL\out\x64\out\inc\__msvc_chrono.hpp(72): note: see declaration of 'std::chrono::is_clock'

D:\GitHub\STL\out\x64>cl /EHsc /nologo /W1 /std:c++latest /wd5285 meow.cpp
meow.cpp

D:\GitHub\STL\out\x64>clang-cl /EHsc /nologo /W1 /std:c++latest meow.cpp
meow.cpp(10,16): error: 'is_clock' cannot be specialized: Specializing this standard library template is forbidden by
      N5014 [time.traits.is.clock]/2 [-Winvalid-specialization]
   10 |         struct is_clock<Kitty<T>> : true_type {};
      |                ^
D:\GitHub\STL\out\x64\out\inc\__msvc_chrono.hpp(72,12): note: marked 'no_specializations' here
   72 |     struct _NO_SPECIALIZATIONS_CITING("N5014 [time.traits.is.clock]/2") is_clock : bool_constant<is_clock_v<_Clock>> {};
      |            ^
D:\GitHub\STL\out\x64\out\inc\yvals_core.h(748,5): note: expanded from macro '_NO_SPECIALIZATIONS_CITING'
  748 |     _NO_SPECIALIZATIONS_MSG("Specializing this standard library template is forbidden by " _Standardese)
      |     ^
D:\GitHub\STL\out\x64\out\inc\yvals_core.h(742,41): note: expanded from macro '_NO_SPECIALIZATIONS_MSG'
  742 | #define _NO_SPECIALIZATIONS_MSG(_Msg) [[_Clang::__no_specializations__(_Msg)]]
      |                                         ^
1 error generated.

D:\GitHub\STL\out\x64>clang-cl /EHsc /nologo /W1 /std:c++latest -Wno-invalid-specialization meow.cpp

D:\GitHub\STL\out\x64>

It was difficult to search the Standard but I didn't find any other occurrences of missed enforcement.

Now all we have to do is remember to keep this current as we implement new features! (Oh yeah, and deal with any fallout in the internal builds and tests, which I will take care of.)

@StephanTLavavej StephanTLavavej removed their assignment Sep 18, 2025
@StephanTLavavej StephanTLavavej moved this from Initial Review to Ready To Merge in STL Code Reviews Sep 18, 2025
@StephanTLavavej
Copy link
Member

Thanks to @MattStephanson for reminding me about <mdspan>'s mapping types! I pushed a commit to enforce WG21-N5014 [namespace.std]/4.3 "The behavior of a C++ program is undefined if it declares [...] an explicit or partial specialization of any member class template of a standard library class or class template" for mapping and allocator rebinds:

Click to expand member class template example:
D:\GitHub\STL\out\x64>type meow.cpp
#include <mdspan>
#include <memory>

template <typename T>
struct Kitty {};

namespace std {
    template <typename T>
    struct layout_left::mapping<Kitty<T>> {};

    template <typename T>
    template <typename U>
    struct allocator<T>::rebind<Kitty<U>> {};
} // namespace std
D:\GitHub\STL\out\x64>cl /EHsc /nologo /W4 /std:c++latest /c /D_HAS_DEPRECATED_ALLOCATOR_MEMBERS=1 meow.cpp
meow.cpp
meow.cpp(9): warning C5285: cannot declare a specialization for 'std::layout_left::mapping': Specializing this standard library template is forbidden by N5014 [namespace.std]/4.3
D:\GitHub\STL\out\x64\out\inc\mdspan(480): note: see declaration of 'std::layout_left::mapping'
meow.cpp(13): warning C5285: cannot declare a specialization for 'std::allocator<_Ty>::rebind': Specializing this standard library template is forbidden by N5014 [namespace.std]/4.3
D:\GitHub\STL\out\x64\out\inc\xmemory(968): note: see declaration of 'std::allocator<_Ty>::rebind'

@StephanTLavavej StephanTLavavej moved this from Ready To Merge to Merging in STL Code Reviews Sep 19, 2025
@StephanTLavavej StephanTLavavej changed the title Mark templates users shouldn't specialize with _NO_SPECIALIZATIONS Mark templates users shouldn't specialize with no_specializations attributes Sep 19, 2025
@StephanTLavavej
Copy link
Member

I'm mirroring this to the MSVC-internal repo - please notify me if any further changes are pushed.

@StephanTLavavej StephanTLavavej merged commit b49a10b into microsoft:main Sep 22, 2025
39 checks passed
@github-project-automation github-project-automation bot moved this from Merging to Done in STL Code Reviews Sep 22, 2025
@StephanTLavavej
Copy link
Member

Thanks for helping users write more conformant code! 😻 🪄 📈

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Something can be improved
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

Use [[clang::no_specializations]] to indicate templates which users are forbidden to specialize
4 participants