Overloading (not specializing) templates in std na

2019-02-13 14:41发布

问题:

This is very pedantic but in C++03 it was apparently non-conforming for a program to overload (not specialize) a template function in the std namespace: see mention of this here and long discussion on comp.lang.c++.moderated

i.e. this was ok:

namespace std
{
    template <>
    void swap (Foo & f, Foo & g)
    {
       // ...
    }
}

but this was not (if I understand correctly...):

namespace std
{
    template <typename T>
    void swap (TempateFoo<T> & f, TempateFoo<T> & g)
    {
       // ...
    }
}

Is this still true in C++11? Also, does this apply to template classes (like std::hash) too, or just template functions?

EDIT: also, is there any example of a standard library implementation such that the latter would break things in practice? And if not, is there a specific reason for disallowing overloads like in the second case above? (what could potentially break in theory?)

回答1:

It is not possible to define a partial specialization of a function template in C++, so your second example defines an overload not a specialization. Since the standard only allows specializations to be added to namespace std, your overload is illegal.

Is this still true in C++11?

Yes.

Also, does this apply to template classes (like std::hash) too, or just template functions?

You can't overload class templates anyway, you can only overload functions. The same rules apply though, you can only specialize a class template if the specialization depends on a user-defined (meaning non-standard) type.

is there a specific reason for disallowing overloads like in the second case above? (what could potentially break in theory?)

As one example, the implementation might want to take the address of a function but if you've overloaded the function then taking the address could cause an ambiguity and fail to compile, meaning you've just broken valid code in the standard library.



回答2:

n3376 17.6.4.2.1

The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std unless otherwise specified. 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.

17.6.4.2.2

The behavior of a C++ program is undefined if it declares

— an explicit specialization of any member function of a standard library class template, or

— an explicit specialization of any member function template of a standard library class or class template, or

— an explicit or partial specialization of any member class template of a standard library class or class template.

A program may explicitly instantiate a template defined in the standard library only if the declaration depends on the name of a user-defined type and the instantiation meets the standard library requirements for the original template.