C++ 在std命名空间中重载(非专门化)模板

C++ 在std命名空间中重载(非专门化)模板,c++,c++11,std,language-lawyer,C++,C++11,Std,Language Lawyer,这是非常迂腐的,但在C++03中,程序在std命名空间中重载(而不是专门化)模板函数显然是不符合要求的:请参见此和 i、 e.这还可以: namespace std { template <> void swap (Foo & f, Foo & g) { // ... } } 名称空间std { 模板 无效掉期(Foo&f、Foo&g) { // ... } } 但这不是(如果我理解正确的话…): 名称空间std {

这是非常迂腐的,但在C++03中,程序在
std
命名空间中重载(而不是专门化)模板函数显然是不符合要求的:请参见此和

i、 e.这还可以:

namespace std
{
    template <>
    void swap (Foo & f, Foo & g)
    {
       // ...
    }
}
名称空间std
{
模板
无效掉期(Foo&f、Foo&g)
{
// ...
}
}
但这不是(如果我理解正确的话…):

名称空间std
{
模板
无效掉期(TempateFoo&f、TempateFoo&g)
{
// ...
}
}
在C++11中仍然是这样吗?此外,这是否也适用于模板类(如
std::hash
),还是仅适用于模板函数

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

n3376 17.6.4.2.1

如果将名称或定义添加到命名空间STD或A,则C++程序的行为是未定义的。 命名空间std中的命名空间,除非另有规定。程序可以添加模板专门化 仅当声明依赖于用户定义的类型时,才将任何标准库模板转换为命名空间std 专门化满足原始模板的标准库要求,并且没有明确定义 禁止使用。

17.6.4.2.2

C++程序的行为如果声明为

则是未定义的。 -标准库类模板的任何成员函数的显式专门化,或

-标准库类或类模板的任何成员函数模板的显式专门化, 或

-标准库类或类的任何成员类模板的显式或部分专门化 模板

只有在声明 取决于用户定义类型的名称,且实例化满足标准库要求
对于原始模板,

,不可能在C++中定义函数模板的部分专门化,因此第二个例子定义了一个重载而不是一个专门化。由于该标准只允许将专门化添加到命名空间
std
,因此您的重载是非法的

在C++11中仍然是这样吗

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

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

是否有特定的理由不允许像上面第二种情况那样的重载?(理论上有什么可能突破?)


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

我认为你不能为模板专门化以外的东西打开
std
名称空间。所以第二个例子仍然是非法的?是的,但我不是100%确定。好吧……我给这个语言律师加上标签是有原因的:)记住这个问题的答案“有没有标准库实现的例子,使得后者在实践中会破坏东西?”可能没有,但这并不意味着它在将来不会破坏(如果标准不允许在
std
命名空间中添加这样的内容).太好了,谢谢!不过,有什么线索可以解释为什么不允许超载吗?这显然是在讨论中提出来的,所以我不得不想象这是一个限制的原因。我现在接受这一点,但如果有人能继续解释这一限制背后的原因,那就太好了:)(我相信一定有人向委员会提出了这一点。)添加重载可能会导致现有的无关调用使用该重载,而不是它们以前使用的任何重载。无关,例如根本不提及您的用户定义类型。专门化无法做到这一点。好的,很好,最后一部分有意义。是部分专门化(例如,std::hash)使用用户定义类型ok,还是完全专业化?如果部分专业化取决于用户定义类型,则可以,例如,
std::hash
是ok的,因为它取决于用户定义类型的
MyTemplate
,这是最后一部分吗(在
std
中对用户定义类型的部分专业化是ok的)在C++03中也是这样吗?“意思是非标准的”--
namespace std
{
    template <typename T>
    void swap (TempateFoo<T> & f, TempateFoo<T> & g)
    {
       // ...
    }
}