将特化注入std命名空间是否可以?

时间:2011-08-05 09:44:37

标签: c++ c++11 template-specialization

在此article on defining your own extensions to ::std::error_code中,作者推荐此代码:

namespace std
{
  template <>
  struct is_error_code_enum<http_error>
    : public true_type {};
}

以便从您自己的错误常量转换为系统错误类型。

这合理吗?将事物放入std命名空间总是让我感到紧张。有没有更好的方法来实现目标?如果做不到这一点,标准的一部分是否可以做到这一点?

2 个答案:

答案 0 :(得分:23)

是的,现有std类型的特化(对于用户定义的类型)是允许放在std命名空间中的唯一事物,只要专业化符合原始模板的要求。

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

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

答案 1 :(得分:8)

这不仅仅是好的 - 在某些情况下这是必不可少的。你不应该做的是在std。

中定义全新的函数/类/模板

std::swap特别是专业化的常见且简单的事情。有些类需要这样做以允许有效的交换,基本上将私有引用交换到交换内部,而不是使用默认的临时和赋值实现。

修改

ildjarn的评论提及ADL - Argument Dependent name Lookup。维基百科页面在“接口”和“批评”部分专门提到了std::swap

Stroustrup(特别版)的第13.5.2节包含std::swap的专业化示例。引用那个......

  

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

我一直认为这表明std::swap的专业化是正确的做法,而且我从来没有过多担心ADL会对此提出疑问,但是可能存在“用于标准库“和”广泛适用的技术“ - 此技术不应用于专门化std::swap来处理不在std中的类型。

特殊版本首次发布时,还可能存在尚未确定的样式问题。 AFAIK,Stroustrup增加了一些额外的附录并应用了一些勘误表,但在其他方面没有对内容进行实质性的修改。

基于维基百科页面, 是混合添加特化和ADL的潜在问题 - 有时你可能会出现歧义,阻止任何查找。如果你混合使用这两种技术,就会发生这种 ,并且ADL知道无论如何都会导致语义问题。但是这个论点只会导致“根本不使用ADL”,但ADL确实存在是有原因的。

嗯,是的,ADL存在是有原因的 - 因此使用时间的非成员函数和运算符与类型一起可见。但std::swap与一种特定类型无关 - 它是通用的,只有特定的特殊化与特定类型相关联。如果您希望std::swap可见,则需要std命名空间。 ADL没有必要做到这一点,正如维基百科页面指出的那样,有人批评ADL。

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

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