【问题标题】:Overloading (not specializing) templates in std namespace在 std 命名空间中重载(非特化)模板
【发布时间】:2013-02-27 05:21:56
【问题描述】:

这是非常迂腐的,但在 C++03 中,程序在std重载(不是专门化)模板函数显然不符合规范命名空间:请参阅 herelong discussion on 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),还是仅适用于模板函数?

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

【问题讨论】:

  • 我认为你不能为模板专业化以外的东西打开std命名空间。
  • 那么第二个例子还是非法的?
  • 是的,但我不是 100% 确定。
  • 好的...我标记了这个语言律师是有原因的 :)
  • 请记住问题的答案“是否有任何标准库实现的示例,这样后者会在实践中破坏事物?” 可能是 NONE,但事实并非如此' t 意味着它将来不会中断(如果标准不允许 such 添加到std 命名空间)。

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


【解决方案1】:

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

在 C++11 中仍然如此吗?

是的。

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

你不能重载类模板,你只能重载函数。但同样的规则也适用,只有当特化依赖于用户定义(即非标准)类型时,您才能特化类模板。

是否有特定原因不允许像上面第二种情况那样重载? (理论上可能会出现什么问题?)

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

【讨论】:

  • 好的,太好了,最后一部分说得通。
  • 是用户定义类型的部分特化(例如std::hash),还是完全特化?
  • 如果部分特化依赖于用户定义的类型是可以的,例如std::hash&lt;MyTemplate&lt;T&gt;&gt; 可以,因为它依赖于MyTemplate&lt;T&gt;,这是一个用户定义的类型
  • 酷,最后一部分(std 中关于用户定义类型的部分特化是可以的)是新的还是在 C++03 中也是如此?
  • “表示非标准” -- I wish it was that clear
【解决方案2】:

n3376 17.6.4.2.1

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

17.6.4.2.2

如果 C++ 程序声明了,则其行为是未定义的

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

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

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

程序可以显式实例化标准库中定义的模板,仅当声明 取决于用户定义类型的名称并且实例化符合标准库要求 用于原始模板。

【讨论】:

  • 太好了,谢谢!但是,任何线索为什么不允许重载?这显然已经引起了足够多的讨论,所以我不得不想象限制是有原因的。
  • 我现在接受这个,但如果有人能跟进这个限制背后的原因,那就太好了:)(我相信一定有人向委员会提出了这个问题。)跨度>
  • 添加重载会导致现有的 unrelated 调用使用该重载,而不是之前使用的任何调用。与根本不提及您的用户定义类型无关。专业化无法做到这一点。
猜你喜欢
  • 2014-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多