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

时间:2013-02-27 05:21:57

标签: c++ c++11 std language-lawyer

这是非常迂腐的但是在C ++ 03中显然不符合程序重载(不是 specialize ){{1}中的模板函数命名空间:请参阅提及此herelong 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) { // ... } } ),或仅适用于模板函数?

编辑:还有,有没有标准库实现的例子,后者会在实践中破坏它?如果没有,是否有一个特殊原因可以解除超载问题,就像上面的第二种情况一样? (理论上可能会破坏什么?)

2 个答案:

答案 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 ++程序的行为是不确定的

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

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

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

只有声明时,程序才能显式实例化标准库中定义的模板 取决于用户定义类型的名称,实例化符合标准库要求 对于原始模板。