这是非常迂腐的但是在C ++ 03中显然不符合程序重载(不是 specialize ){{1}中的模板函数命名空间:请参阅提及此here和long discussion on comp.lang.c++.moderated
即。这没关系:
std
但这不是(如果我理解正确的话......):
namespace std
{
template <>
void swap (Foo & f, Foo & g)
{
// ...
}
}
在C ++ 11中这仍然是正确的吗?此外,这是否也适用于模板类(如namespace std
{
template <typename T>
void swap (TempateFoo<T> & f, TempateFoo<T> & g)
{
// ...
}
}
),或仅适用于模板函数?
答案 0 :(得分:8)
无法在C ++中定义函数模板的部分特化,因此您的第二个示例定义了一个重载而不是一个特化。由于标准只允许将特化添加到命名空间std
,因此您的重载是非法的。
这在C ++ 11中是否仍然如此?
是
此外,这是否也适用于模板类(如std :: hash),或仅适用于模板函数?
无论如何你都不能重载类模板,你只能重载函数。但是,相同的规则适用,如果专业化取决于用户定义的(意为非标准的)类型,则只能专门化类模板。
是否有一个特殊原因可以解除超载问题,例如上面的第二种情况? (理论上可能会破坏什么?)
作为一个例子,实现可能想要获取函数的地址,但是如果你重载了函数,那么获取地址可能会导致歧义并且无法编译,这意味着你刚刚破坏了标准中的有效代码库。
答案 1 :(得分:6)
n3376 17.6.4.2.1
如果它向名称空间std或a添加声明或定义,则C ++程序的行为是未定义的 除非另有说明,否则命名空间std中的命程序可以添加模板专业化 对于任何标准库模板到命名空间std,仅当声明取决于用户定义的类型时 并且专业化符合原始模板的标准库要求,并未明确说明 禁止的。
17.6.4.2.2
如果声明
,则C ++程序的行为是不确定的- 标准库类模板的任何成员函数的显式特化,或
- 标准库类或类模板的任何成员函数模板的显式特化, 或
- 标准库类或类的任何成员类模板的显式或部分特化 模板。
只有声明时,程序才能显式实例化标准库中定义的模板 取决于用户定义类型的名称,实例化符合标准库要求 对于原始模板。