在C++ 20中,不再允许在std中为程序定义类型专门化函数模板吗?

Dan*_*ica 25 c++ std template-specialization function-templates c++20

来自cppreference.com的报价:

添加模板特化

允许为任何标准库添加模板特化(从C++ 20开始)| 模板到命名空间std只有当声明依赖于至少一个程序定义的类型并且特化满足原始模板的所有要求时,除非禁止这样的特化.

是否意味着,从C++ 20开始,将std不再允许将函数模板的特化添加到用户定义类型的命名空间中?如果是这样,它意味着许多现有代码可能会破坏,不是吗?(在我看来,这是一种"激进"的改变.)此外,它会向这些代码注入未定义的行为,这不会触发编译错误(警告有希望).

Nat*_*ica 24

现在看来它绝对是那样的.以前[namespace.std]包含

只有当声明取决于用户定义的类型并且特化符合原始模板的标准库要求且未明确禁止时,程序才可以将任何标准库模板的模板特化添加到命名空间std.

目前的草案表明

除非明确禁止,否则程序可以将任何标准库类模板的模板特化添加到命名空间std,前提是(a)添加的声明取决于至少一个程序定义的类型,以及(b)专业化满足标准库的要求.原始模板.

强调我的

它看起来像纸张Thou Shalt Not Specialize std功能模板!由Walter E. Brown负责.在其中,他详述了为什么要改变这一点的一些原因,例如:

  • Herb Sutter:"专业化不参与超载.[...]如果要自定义函数库模板并希望该自定义参与重载解析(或者,在完全匹配的情况下始终使用),请将其设置为普通旧函数,而不是专门化.并且,如果您确实提供了重载,请避免提供专业化."
  • David Abrahams:"使用函数模板专门化是错误的[因为]它会以错误的方式与重载进行交互.[...]例如,如果你的专业正规std::swapstd::vector<mytype>&,您的专业将不会选择了在特定标准的载体swap,因为特没有重载过程中考虑."
  • Howard Hinnant:"这个问题已经解决了很长时间....无视Dave在这方面的专家意见/答案,这是你自己的危险."
  • Eric Niebler:"[因为] C++在模板中解析函数调用的方式非常糟糕...,[w]进行无条件调用 swap,以便找到可能在相关名称空间[...]中定义的重载,并且我们这样做,using std::swap以便在没有这样的情况下发生这种情况.重载,我们找到std命名空间中定义的默认版本."
  • 高完整性C++编码标准:"过载分辨率不考虑功能模板的显式特化.只有在重载决策选择了函数模板后,才会考虑任何明确的特化."


Sto*_*ica 15

不是那么激进.这一变化是基于沃尔特·E·布朗的这篇论文.这篇论文的理论基础相当深入,但最终归结为:

  1. 功能模板的专业化作为定制点是相当差的.在这方面,重载和ADL要好得多.本文还讨论了其他定制点.
  2. 标准库已经不太依赖这个糟糕的定制点了.
  3. 实现的措辞改变实际上允许将整个声明添加到明确允许的命名空间std(不仅仅是特化).所以现在有更好的定制点.

鉴于#1和#2,现有代码不太可能破解.或者至少,这还不足以成为一个主要问题.在过去使用过auto并且register也"破坏"的代码,但是那些微不足道的C++代码并没有停止进展.