8

这是非常迂腐的,但在 C++03 中,程序在命名空间中重载(而不是专门化)模板函数显然是不符合规范的std:请参阅此处提及的内容和关于 comp.lang.c++.moderated 的长时间讨论

即这没关系:

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

但这不是(如果我理解正确的话......):

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

这在 C++11 中仍然成立吗?此外,这是否也适用于模板类(如std::hash),还是仅适用于模板函数?

编辑:另外,有没有标准库实现的例子,这样后者会在实践中破坏东西?如果没有,是否有特定原因不允许像上面第二种情况那样重载?(理论上可能会破坏什么?)

4

2 回答 2

8

无法在 C++ 中定义函数模板的部分特化,因此您的第二个示例定义了重载而不是特化。由于该标准只允许将特化添加到 namespace std,因此您的重载是非法的。

这在 C++11 中仍然成立吗?

是的。

此外,这是否也适用于模板类(如 std::hash),还是仅适用于模板函数?

无论如何你不能重载类模板,你只能重载函数。但是,同样的规则适用,如果特化依赖于用户定义的(即非标准)类型,您只能特化类模板。

在上面的第二种情况下,是否有禁止重载的具体原因?(理论上可能会破坏什么?)

例如,实现可能想要获取函数的地址,但如果您重载了函数,那么获取地址可能会导致歧义并无法编译,这意味着您刚刚破坏了标准库中的有效代码。

于 2013-02-27T13:22:30.310 回答
6

n3376 17.6.4.2.1

如果 C++ 程序将声明或定义添加到命名空间 std 或命名空间 std 内的命名空间,则 C++ 程序的行为是未定义的,除非另有说明。只有当声明依赖于用户定义的类型并且特化满足原始模板的标准库要求并且没有明确禁止时,程序才能将任何标准库模板的模板特化添加到命名空间 std。

17.6.4.2.2

如果 C++ 程序声明了,那么它的行为是未定义的

— 标准库类模板的任何成员函数的显式特化,或

— 标准库类或类模板的任何成员函数模板的显式特化,或

— 标准库类或类模板的任何成员类模板的显式或部分特化。

只有当声明依赖于用户定义类型的名称并且实例化满足标准库对原始模板的要求时,程序才能显式实例化标准库中定义的模板。

于 2013-02-27T05:31:29.217 回答