【问题标题】:Adding template specialization in std namespace在 std 命名空间中添加模板特化
【发布时间】:2014-11-17 12:28:46
【问题描述】:

背景:
我试图回答问题Why isn't my overloading < operator not working for STL sort。我的建议之一(除了使用谓词)是在命名空间 std 中移动 std::string 的自定义 operator &lt;,以便编译器可以优先使用它而不是模板版本。

以闪电般的速度,该答案被一位知名用户的以下评论否决:

这是未定义的行为,您不能添加声明 命名空间 std 因为它可以改变标准的行为 库组件

我的问题:
是否可以为 stl 类型添加模板特化,即使此特化的声明不包含用户定义的数据类型?


附言。我已经删除了我的答案,因为我担心它可能是错误的

【问题讨论】:

标签: c++ stl language-lawyer


【解决方案1】:

STL 类旨在以明确定义的方式使用,即使用 POD 类型或符合类要求的 STL 类或实现类要求的用户定义类型来实例化它们。

您也不应该从 STL 类型继承;最好创建一个以 STL 对象为成员的新类;那么你可以实现与 STL 对象的方法签名匹配的公共方法。

在不深入探讨此规则的所有基本原理的情况下,这是使用 STL 类的最可移植且可能长期存在的方式。它在特定于应用程序的类和 STL 类之间划清界限。

【讨论】:

    【解决方案2】:

    C++11,[namespace.std]§1:

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

    上述段落明确禁止不依赖于用户定义类型的特化。

    至于动机:您不会添加模板专业化,而是添加单独的声明,这也是被禁止的。

    【讨论】:

    • 即使我将std::basic_string::operator &lt; 专门用于charT = char,它仍然会出错吗?
    • @MohitJain:是的,它仍然是错误的:你只能将它专门用于用户定义的类型,而不是库定义的或内置的类型。
    • 灰色区域是您将其专门用于其他人的用户定义类型。例如。试图将std::swap 专门用于boost:: 类型不是标准的未定义行为,因为它们没有给boost:: 一个特殊状态。专攻char 是完全错误的。
    • @MSalters 我不会真的称它为灰色区域 - 除了内置和 std 之外的所有内容都是用户定义的,所以它很简单。即使一个类型来自第 3 方库,它也是 your 程序的一部分,因此 you 应该能够在必要时处理它。
    • @Angew 好吧,按照 C++ 标准可能没问题;您使用的库可能不行。
    【解决方案3】:

    标准库足够灵活,有许多用于分配器、谓词等的额外参数。因此,如果您要向 std 命名空间添加一些东西,似乎您以错误的方式追求目标。

    休息一下换个思路,然后阅读 STL 源代码并按照它进行游戏。

    【讨论】:

    • 是的。特别是,STL 通常接受函数对象作为默认 std::less&lt;T&gt; 的替代(即包装 operator&lt; 的函数对象)
    【解决方案4】:

    Angew 得到了相关的引用,但解释有缺陷。

    您建议在namespace std 中添加模板特化。 在取决于用户定义的类型时才允许这样做。你特别提到它没有。因此,不满足例外的先决条件,适用基本规则(无添加)。不行。

    【讨论】:

    • 感谢您的回答。我希望我能选择正确的 2 个答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-24
    • 1970-01-01
    相关资源
    最近更新 更多