C++ 将专门化注入std名称空间可以吗?

C++ 将专门化注入std名称空间可以吗?,c++,c++11,template-specialization,C++,C++11,Template Specialization,在本文中,作者推荐以下代码: namespace std { template <> struct is_error_code_enum<http_error> : public true_type {}; } 名称空间std { 模板 结构是\u错误\u代码\u枚举 :public true_type{}; } 以便启用从您自己的错误常量到系统错误类型的转换 这合理吗?把东西放入std名称空间总是让我感到紧张。有没有更好的方法来实现目标?如果做不到这

在本文中,作者推荐以下代码:

namespace std
{
  template <>
  struct is_error_code_enum<http_error>
    : public true_type {};
}
名称空间std
{
模板
结构是\u错误\u代码\u枚举
:public true_type{};
}
以便启用从您自己的错误常量到系统错误类型的转换

这合理吗?把东西放入
std
名称空间总是让我感到紧张。有没有更好的方法来实现目标?如果做不到这一点,标准中是否有一部分规定这样做总是可以的?

是的,现有std类型的专门化(对于用户定义的类型)是唯一允许放在
std
命名空间中的内容,只要专门化满足原始模板的要求

参见C++0x草案中的17.6.4.2.1


当然,禁止使用新类型、函数重载和其他任何内容。但是允许对现有模板进行专门化。

这不仅可以,在某些情况下也是必要的。您不应该在std中定义全新的函数/类/模板

std::swap
尤其是一种常见且简单的专业化方法。有些类需要这样做才能实现高效的交换,基本上是将私有引用交换到交换内部,而不是使用默认的临时和分配实现

编辑

ildjarn的评论提到了ADL-。维基百科页面在“接口”和“批评”部分特别提到了
std::swap

Stroustrup(特别版)第13.5.2节包括
std::swap
的专门化示例。引用这句话

标准库(16.3.9、20.3.16)中使用了
less()
swap()
的这些专门化。此外,它们是广泛应用的技术的例子

我一直认为,专业化
std::swap
是正确的做法,我从来没有担心过ADL会质疑这一点,但“在标准库中使用”和“广泛应用的技术”之间可能存在差距-不应使用此技术专门处理
std::swap
中没有的类型

也有可能在特别版第一次出版时,有一个风格问题尚未决定。最后,斯特劳斯特鲁普增加了一些额外的附录,并应用了一些勘误表,但没有对内容进行实质性修改

根据维基百科的页面,将专业知识和ADL混合在一起可能会有一个潜在的问题——有时,你会因为不明确而无法进行任何查找。这只有在混合使用这两种技术的情况下才会发生,而且众所周知,ADL会导致语义问题。但这一论点只会导致“根本不使用ADL”,但ADL的存在是有原因的

嗯,是的,ADL的存在是有原因的——因此,与时间一起工作的非成员函数和运算符与类型一起可见。但是
std::swap
与一个特定类型没有关联-它是泛型的,只有特定的专门化与特定类型关联。如果希望
std::swap
可见,则需要
std
命名空间。ADL并不是实现这一目标的必要条件,正如维基百科页面所指出的,ADL也受到了批评

这意味着,基本上,我不知道。我有自己的理由。他们不一定同意更广泛的风格规则。当然,这一评论证明,专业化
std::swap
并不是必要的-您可以提供自己单独的
swap
,并依赖ADL。也许这是首选


检查完后,我可能会回来再次编辑。

您有更好的答案,但@Steve314包含了一些重要的细节,在某些情况下,您必须这样做。我可能会等待几个小时(仅根据一般原则),然后可能会接受这个。
std::swap
不应该被专门化或重载——相反,应该将一个
swap
免费函数放在与被交换的类型相同的命名空间中,然后让ADL来完成其余的工作。@ildjarn-谢谢-我还不确定你是对的,但是,在相当长的一段时间内,edit.ADL在主要编译器中被广泛破坏,因此专门化
std::swap
成为标准做法。但是,对于现代的、更标准的符合编译器,不再需要这种解决方法。依赖ADL的问题是许多代码显式地调用
std::swap
,而不是
swap
。我真的看不出有什么理由支持使用ADL进行
swap
。我大部分时间都能看到它在工作,但我不明白为什么它会是一个上级option@jalf-我认为我的问题是,我认为重载不是从许多不同的函数中选择,而是从一个函数的多个实现中选择编译时调度。我认为名称空间是函数名的一部分。从这个角度来看,在这种情况下依赖ADL是可怕的-
whatever::swap
std::swap
在概念上是两个不相关的函数,而不仅仅是不同的实现。问题是,这可能只是意味着我的思维模式错误。