Will specialization of function templates in std for program-defined types no longer be allowed in C++20?
As it stands now it definitly looks that way. Previously [namespace.std] contained
A program may add a template specialization for any standard library template to namespace std only if the declaration depends on a user-defined type and the specialization meets the standard library requirements for the original template and is not explicitly prohibited.
While the current draft states
Unless explicitly prohibited, a program may add a template specialization for any standard library class template to namespace std provided that (a) the added declaration depends on at least one program-defined type and (b) the specialization meets the standard library requirements for the original template.
emphasis mine
And it looks like the paper Thou Shalt Not Specialize std Function Templates! by Walter E. Brown is responsible for it. In it he details an number of reason why this should be changed such as:
- Herb Sutter: “specializations don’t participate in overloading. [...] If you want to customize a function base template and want that customization to participate in overload resolution (or, to always be used in the case of exact match), make it a plain old function, not a specialization. And, if you do provide overloads, avoid also providing specializations.”
- David Abrahams: “it’s wrong to use function template specialization [because] it interacts in bad ways with overloads. [...] For example, if you specialize the regular
std::swap
forstd::vector<mytype>&
, your specialization won’t get chosen over the standard’s vector specificswap
, because specializations aren’t considered during overload resolution.”- Howard Hinnant: “this issue has been settled for a long time. . . . Disregard Dave’s expert opinion/answer in this area at your own peril.”
- Eric Niebler: “[because of] the decidedly wonky way C++ resolves function calls in templates. . . , [w]e make an unqualified call to
swap
in order to find an overload that might be defined in [...] associated namespaces[...] , and we dousing std::swap
so that, on the off-chance that there is no such overload, we find the default version defined in the std namespace.”- High Integrity C++ Coding Standard: “Overload resolution does not take into account explicit specializations of function templates. Only after overload resolution has chosen a function template will any explicit specializations be considered.”
Not really that radical. This change is based on this paper from Walter E. Brown. The paper goes into rationale rather deeply, but ultimately it boils down to this:
- Specialization of function templates is rather poor as a customization point. Overloading and ADL are much better in that regard. There are other customization points discussed in the paper as well.
- The standard library doesn't rely on this poor customization point too much already.
- The wording change that's put into place actually permits adding entire declarations to namespace std (not just specializations) where it's explicitly permitted. So now there are better customization points.
Given #1 and #2, it's rather unlikely existing code will break. Or at least, not enough for this to be a major problem. Code that used auto
and register
also "broke" in the past, but that minuscule amount of C++ code didn't stop progress.