简体   繁体   English

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

[英]Will specialization of function templates in std for program-defined types no longer be allowed in C++20?

Quote from cppreference.com : 来自cppreference.com的报价:

Adding template specializations 添加模板特化

It is allowed to add template specializations for any standard library |class (since C++20)| 允许为任何标准库添加模板特化(从C ++ 20开始)| template to the namespace std only if the declaration depends on at least one program-defined type and the specialization satisfies all requirements for the original template, except where such specializations are prohibited. 模板到命名空间std只有当声明依赖于至少一个程序定义的类型并且特化满足原始模板的所有要求时,除非禁止这样的特化。

Does it mean, that starting from C++20, adding specializations of function templates to the std namespace for user-defined types will be no longer allowed? 这是否意味着,从C ++ 20开始,将不再允许将函数模板的特化添加到用户定义类型的std命名空间? If so, it implies that many pieces of existing code can break, doesn't it? 如果是这样,它意味着许多现有代码可能会破坏,不是吗? (It seems to me to be kind-of a "radical" change.) Moreover, it will inject into such codes undefined behavior, which will not trigger compilations errors (warnings hopefully will). (在我看来,这是一种“激进”的改变。)此外,它会向这些代码注入未定义的行为,这不会触发编译错误(警告有希望)。

As it stands now it definitly looks that way. 现在看来它绝对是那样的。 Previously [namespace.std] contained 以前[namespace.std]包含

A program may add a template specialization for any standard library template to namespace std only if the declaration depends on a user-defined type and the specialization meets the standard library requirements for the original template and is not explicitly prohibited. 只有当声明取决于用户定义的类型并且特化符合原始模板的标准库要求且未明确禁止时,程序才可以将任何标准库模板的模板特化添加到命名空间std。

While the current draft states 目前的草案表明

Unless explicitly prohibited, a program may add a template specialization for any standard library class template to namespace std provided that (a) the added declaration depends on at least one program-defined type and (b) the specialization meets the standard library requirements for the original template. 除非明确禁止,否则程序可以将任何标准库类模板的模板特化添加到命名空间std,前提是(a)添加的声明取决于至少一个程序定义的类型,以及(b)专业化满足标准库的要求。原始模板。

emphasis mine 强调我的

And it looks like the paper Thou Shalt Not Specialize std Function Templates! 它看起来像纸张Thou Shalt Not Specialize std功能模板! by Walter E. Brown is responsible for it. 由Walter E. Brown负责。 In it he details an number of reason why this should be changed such as: 在其中,他详述了为什么要改变这一点的一些原因,例如:

  • Herb Sutter: “specializations don't participate in overloading. Herb Sutter:“专业化不参与超载。 [...] If you want to customize a function base template and want that customization to participate in overload resolution (or, to always be used in the case of exact match), make it a plain old function, not a specialization. [...]如果要自定义函数库模板并希望该自定义参与重载解析(或者,在完全匹配的情况下始终使用),请将其设置为普通旧函数,而不是专门化。 And, if you do provide overloads, avoid also providing specializations.” 并且,如果您确实提供了重载,请避免提供专业化。“
  • David Abrahams: “it's wrong to use function template specialization [because] it interacts in bad ways with overloads. David Abrahams:“使用函数模板特化是错误的[因为]它会以错误的方式与重载进行交互。 [...] For example, if you specialize the regular std::swap for std::vector<mytype>& , your specialization won't get chosen over the standard's vector specific swap , because specializations aren't considered during overload resolution.” [...]例如,如果你专门定期std::swap for std::vector<mytype>& ,你的专业化将不会超过标准的矢量特定swap ,因为在重载解析期间不考虑特化“。
  • Howard Hinnant: “this issue has been settled for a long time. Howard Hinnant:“这个问题已经解决了很长时间。 . . . Disregard Dave's expert opinion/answer in this area at your own peril.” 无视Dave在这方面的专家意见/答案,这是你自己的危险。“
  • Eric Niebler: “[because of] the decidedly wonky way C++ resolves function calls in templates. Eric Niebler:“[因为] C ++在模板中解析函数调用的方式非常糟糕。 . . , [w]e make an unqualified call to swap in order to find an overload that might be defined in [...] associated namespaces[...] , and we do using std::swap so that, on the off-chance that there is no such overload, we find the default version defined in the std namespace.” ,[w] e进行无条件调用swap ,以便找到可能在相关命名空间[...]中定义的重载,并且我们using std::swap以便在关闭时如果没有这样的重载,我们会找到std命名空间中定义的默认版本。“
  • High Integrity C++ Coding Standard: “Overload resolution does not take into account explicit specializations of function templates. 高完整性C ++编码标准:“过载分辨率不考虑功能模板的显式特化。 Only after overload resolution has chosen a function template will any explicit specializations be considered.” 只有在重载决策选择了函数模板后,才会考虑任何明确的特化。“

Not really that radical. 不是那么激进。 This change is based on this paper from Walter E. Brown . 这一变化是基于沃尔特·E·布朗的这篇论文 The paper goes into rationale rather deeply, but ultimately it boils down to this: 这篇论文的理论基础相当深入,但最终归结为:

  1. Specialization of function templates is rather poor as a customization point. 功能模板的专业化作为定制点是相当差的。 Overloading and ADL are much better in that regard. 在这方面,重载和ADL要好得多。 There are other customization points discussed in the paper as well. 本文还讨论了其他定制点。
  2. The standard library doesn't rely on this poor customization point too much already. 标准库已经不太依赖这个糟糕的定制点了。
  3. The wording change that's put into place actually permits adding entire declarations to namespace std (not just specializations) where it's explicitly permitted. 实现的措辞改变实际上允许将整个声明添加到明确允许的命名空间std(不仅仅是特化)。 So now there are better customization points. 所以现在有更好的定制点。

Given #1 and #2, it's rather unlikely existing code will break. 鉴于#1和#2,现有代码不太可能破解。 Or at least, not enough for this to be a major problem. 或者至少,这还不足以成为一个主要问题。 Code that used auto and register also "broke" in the past, but that minuscule amount of C++ code didn't stop progress. 使用autoregister代码在过去也“破了”,但是那些微不足道的C ++代码并没有停止进展。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM