C++ 17的特征删除和删除

技术的进步是通过发明新的做事方式和抛弃旧的方式来实现的。C++标准化委员会同时在增加新的特性和逐步删除旧的特性,因为我们已经发现了更好的编写代码的方法。虽然功能删除可能会让人恼火,但从程序员需要改变旧的代码基以使其符合新标准的意义上说,它们也很重要。特征删除简化了核心语言和标准库,避免了永远增加复杂性的厄运。此外,删除旧的特性使读写代码更容易。C++将永远是一种语言,它为程序员提供了许多写作的方法,但是通过去除低劣的技术,更容易选择一种更现代的剩余技术。

null

在Visual C++团队中,我们试图帮助程序员实现代码库的现代化,并利用新的标准,同时避免不必要的和不及时的中断。VisualC++本身是一个几十年的代码库,我们了解遗留的代码库是多么宝贵(因为它们是多年的开发和测试的产物),以及它们是多么难改变。虽然我们经常发布新的特性以及如何使用这些特性,但是这个帖子将解释最近完成的C++ 17标准对旧的特性做了什么,以及将来对2017个工具集更新的期望。我们希望使工具集更新尽可能轻松,以便您可以继续以兼容的方式编译代码。准备好后,可以启用编译器选项,开始将代码迁移到新标准(并远离非标准行为),并使用其他编译器/库选项(暂时!)禁用破坏性的新功能、恢复已删除的功能,并消除弃用警告。

我们最近实现了其他编译器长期支持的标准版本切换,允许程序员以自己的速度迁移到较新的标准。这意味着我们可以相对更积极地实现突破源代码的更改(包括但不限于功能删除和否决),当它们受到/std:c++17 以及/std:c++latest 开关,因为它们不会影响/std:c++14 默认值(这些开关确实存在复杂性成本,因为它们增加了编译器可以在其中操作的模式的数量。)

C++标准遵循一定的过程来去除特征。通常(但不总是),特性首先被“弃用”。这是一个官方用语,基本上相当于委员会在特写上愁眉苦脸。不推荐使用的特性的标准见本文件末尾的特别章节(附录D)。尽管不推荐使用的特性仍然是标准的,并且必须由一致的实现来支持,但不推荐使用会让世界注意到删除是可能的(但不能保证)(请注意,允许实现对任何内容发出警告,但它们绝对可以对不推荐使用的特性的使用发出警告。标准现在有了一个属性,用于标记代码以发出这样的警告。)在下面的标准中,不推荐使用的特性可以完全删除。

如果您好奇,相关标准是D[depr]/2“这些是不推荐使用的特性,其中不推荐使用的定义为:本国际标准当前版本的规范性,但已被确定为从未来版本中删除的候选。一个实现可以用不推荐使用的属性(10.6.4)声明本节中描述的库名称和实体。“和10.6.4[dcl.attr.deprecated]/1”不推荐使用的属性标记可以用来标记仍然允许使用的名称和实体,但由于某些原因不鼓励使用。[注意:特别是,deprecated适用于被视为过时或不安全的名称和实体-结束语]”。

从技术上讲,即使是删除也不是一个功能的终点。实现可以符合C++ 17,但接受C++ 17中删除的特性作为扩展。例如,STL的Standardese有一个“Zombie names”部分,表示“在namespace std中,以下名称是为先前的标准化保留的”。本质上,C++ 17是说,虽然它不指定AutoTypTR或unAyl函数等,但一致的C++ 17程序不允许干扰这些名称(例如,用宏),因此符合C++ 17 STL实现可以提供AutoTypTR等作为非C++ 17标准扩展。这使得实现者可以选择是否从物理上删除特性,并且使委员会更容易从标准中删除特性。

因此,在Visual C++的C++ 17模式下,我们正在实现特征移除和删除警告,目的是永久地移除未来的特征(可能是遥远的未来,但总有一天)。其中一些是在VS 2017 15.3中发布的。VS 2017 15.5(第二次工具集更新)中提供了更多信息,随着委员会继续工作,您可以预期否决和删除将无限期地继续下去(例如std::relu ops有望失败)。

如何帮助加速C++ 17的采用

第1a条。下载 最新发布的VS (并在生产中使用),和/或

第1b条。下载 VS的最新预览版本 (并对整个代码库进行测试),和/或

1摄氏度。下载 “每日”MSVC工具集构建 (并对整个代码库进行测试)。

2.编译/std:c++17 或者/std:c++latest (此时,它们能够实现相同的特征,并且通过宏几乎无法区分,但是当我们开始执行C++ 20时它们会分叉)。

3.报告工具集错误。我们试图在固态中释放新的特性,只限于标准本身的模糊性,但是C++是复杂的,我们并不完美,所以会有bug。

4.更新代码库以避免删除和弃用的特性,并在实现新特性时对其他破坏源代码的更改作出反应(例如,每次STL引入一个新函数,如std::clamp()或std::reduce(),任何带有“using namespace std;”指令及其自身的钳制/减少等标识符可能会被破坏。)

5.(重要!)您很可能会在第三方库中遇到无法修改(很容易或根本无法修改)的破坏源代码的更改。我们尝试提供转义图案填充,以便您可以恢复已删除的功能或消除弃用警告并继续工作,但首先,请向相关库维护人员报告此类问题。通过帮助他们更新代码,你会帮助更多的C++程序员,就像你一样。

在过去的几年中,VisualC++团队已经开始用我们的开发工具集和选项来构建和测试许多开源项目和库。std:c++17. 我们自己正在发现并报告突破性的更改,但我们无法构建所有内容,因此我们需要您的帮助。

我们的弃用策略

*在C++ 14模式(默认)中,我们警告非标准机器(例如:STD::Tr1)。这些警告可以以细粒度的方式消除。

*在C++ 17模式下,我们删除非标准机械(例如:STD::Tr1)。这种机器可以精细地修复(然后,它将发出弃用警告,除非静音。)

*在STL的下一个主要的二进制不兼容版本(内部称为“WCFB02”)中,我们已经永久地删除了这个非标准机器(例如std::tr1)。

*在C++ 14模式(默认)中,我们目前不警告在C++ 14中被禁止的特征(例如,AutoMyPTR,它最初被C++ 11所禁止),也不警告C++中移除的特征(例如AutoMyPTR,或者STD::Falm分配器支持,它在没有被删除的情况下被删除)。我们保留将来添加此类警告的权利,但不太可能这样做。

*在C++ 17模式下,我们删除在C++ 17标准中删除的特征(例如AutoMyPTR)。目前,它们可以以某种细粒度的方式进行恢复。理想情况下,它们将在未来某个时间点被永久移除(例如,默认模式将首先从C++ 14切换到C++ 17,然后有一天C++ 14模式将完全被删除——在这一点上,传统的C+14-BUT-NOT-17特性,如AutoPPTR也应该完全放弃)。

*在C++ 17模式下,我们警告所有在C++ 17标准中被禁止的库特征(包括在以前的标准中被禁止的特性,如),其中一个例外(D.5[DEPR .C.Healths])不赞成“STDIO .H>族,但我们不打算对此提出警告。这些C++ 17的弃用警告可以以细粒度的方式被沉默(基本上,附件D的每个部分可以独立地沉默),或者以粗粒度的方式(沉默所有C++ 17的警告警告,而不是其他的警告警告)。

*我们希望重复C++ 20和以后的模式。

C++ 17特征移除-技术细节

* N4190型 正在删除autou ptr、randomu shuffle()和旧的内容

在VS 2017 15.3(及更早版本)中实施。通过将u HAS u AUTO u PTR u ETC定义为1来还原(因此上面的“有点细粒度”)。

自动u ptr被唯一的u ptr取代。

一元函数和二元函数通常是不必要的。在C++ 98/03时代,许多用户定义的函数对象类从这些基类派生出来,试图模仿STL约定。然而,STL容器和算法从来都不需要这种继承(或者它们提供的typedef)。只有函数对象“adaptors”(如bind1st())需要这样的typedef。因此,如果您有从一元函数或二元函数派生的类,则可以消除继承。否则,您可以直接提供typedef。

bind1st()和bind2nd()被bind()和lambdas取代。

ptru fun()已经不再是必需的了——现代机器直接使用函数指针(STL算法也一直如此)。

memu fun()家族已被memu fn()取代。此外,任何遵循invoke()协议的操作(如std::function)都可以直接使用指向成员的指针。

随机u shuffle()被shuffle()取代。

* P0004R1型 “删除不推荐使用的Iostreams别名”

在VS 2017 15.3(及更早版本)中实施。通过定义还原的u HAS u OLD u IOSTREAMS u MEMBERS为1。在STL测试套件之外不太可能遇到。

* P0003R5型 “正在删除动态异常规范”

新实施于VS 2017 15.5。可以通过定义1意外的u HAS u来还原库部件。

* P0302R1型 “正在删除std::function中的分配器支持”, 长荣2385 “function::assign allocator参数没有意义”, 长荣2921 “打包的任务和类型已擦除的分配器”, 长荣2976 “悬挂对打包的u任务使用u分配器专门化”

新实施于VS 2017 15.5(lwg2385以前是用一个不同的宏实现的。)通过定义u HAS u FUNCTION u ALLOCATOR u SUPPORT恢复为1,尽管它既不可靠地实现,也不可移植到其他甚至没有尝试过的实现中(这被证明是更明智的做法)。

非标准功能的弃用和删除-技术详细信息

*非标准std::tr1命名空间和仅tr1的机器

在VS 2017(15.3)中实现了C++ 17模式的删除。通过定义还原u已将u TR1u命名空间设置为1。

在VS 2017 15.5中新弃用了“警告STL4002:非标准std::tr1命名空间和仅tr1机器已弃用并将被删除”。您可以定义u SILENCE u TR1 u NAMESPACE u DEPRECATION u WARNING来确认您已收到此警告。“

*非标准std::identity结构

在VS 2017(15.3)中实现了C++ 17模式的删除。通过定义u已将u IDENTITY u STRUCT还原为1。

在VS 2017 15.5中新弃用了“警告STL4003:非标准std::identity结构已弃用并将被删除”。您可以定义u SILENCEu IDENTITYu STRUCTu DEPRECATIONu警告以确认您已收到此警告。“

*非标准std::tr2::sys命名空间

在C++ 14模式下新删除,在VS 2017 15.5中以C++ 17模式删除。通过定义还原的u HAS u TR2 u SYS u NAMESPACE为1。发出“警告STL4018:非标准std::TR2::SYS NAMESPACE已弃用并将被删除。它被std::experimental::filesystem取代。您可以定义u SILENCEu TR2u SYSu NAMESPACEu DEPRECATIONu WARNING来确认您已收到此警告。“

C++ 17特征背诵-技术细节

这些弃用警告是在VS 2017 15.5中新实现的。 P0174R2型 “弃用残留库部件”, P0521R0型 “正在弃用共享的u ptr::unique()”, P0618R0型 “Deprecating”,以及其他文章添加了这些部分(例如, P0005R4型 “not u fn()”添加了一个功能,并弃用了not1()、not2()和typedefs的结果类型族。尤其是, P0604R0型 “invokeu result,isu invocable,isu nothrowu invocable”在VS 2017 15.3中实现,但其对resultu of的弃用在VS 2017 15.5中新实现。)

正如每个警告消息所述,用于静默的粗粒度宏是u SILENCE u ALL u CXX17 u DEPRECATION u WARNINGS。以下是部分及其相关的警告消息,我们试图在其中提供非常详细和有用的信息:

D.4[DEPR.CPP.Healths]:“警告STL400:< CCOMPUTE,在C++ 17中被弃用。您可以定义SySalistyCX1717CII Head ErrPraceReal-Type警告或SyInsialAxCx17 17DePress警告,以确认您已经收到了这个警告。”

“警告”STL45.:STRSoS>在C++ 17中被禁止。可以定义“SySistNo.CXX17StruthEntRebug”警告或“SyInsialAxCX1717”警告,以确认您已经收到了此警告。

D.7[DEPR,UNIFOT]:“警告STL406:STD::UNCUTHTHUBECTORATIONE())在C++ 17中被弃用。它被STD::UNCUTHOTXExpUTHORSE()取代,复数。您可以定义u SILENCEu CXX17u UNCAUGHTu EXCEPTIONu DEPRECATIONu WARNING或u SILENCEu ALLu CXX17u DEPRECATIONu WARNINGS来确认您已收到此警告。“

D.8.1[depr.weak.resultu type]和D.8.2[depr.func.adapter.typedefs]:“警告STL4007:许多结果类型typedefs和所有参数类型,第一个参数类型,第二个AgutuMutType类型DEFS在C++ 17中被弃用。您可以定义“SySalistyCX1717AdvultSype”Debug StRebug,警告或“SyInsialAxCx1717DePractIsTi警告”,以确认您已经收到了此警告。

D.83[DEP.Neops]:“警告STL48:STD::NOT1()、STD::NOT2()、STD::unAythOngEnter和STD::BialyLoad在C++ 17中被弃用。它们被STD:NothIff())取代。您可以定义u SILENCE u CXX17 u NEGATORS u DEPRECATION u WARNING或u SILENCE u ALL u CXX17 u DEPRECATION u WARNINGS来确认您已收到此警告。”

D.9[DEPR默认。分配器]:“警告STL49:STD::分配器<空虚>在C++ 17中被禁止。你可以定义SySalistyCx17OalLoistaVoIDuDePractIORION警告或SySistNo.AlxCx1717DePractIsTi警告,以确认您已经收到了这个警告。”

D.9[DEPR默认。分配器]:“警告STL4010:STD的各种成员::分配器在C++ 17中被弃用。使用STD::AlalActuffyType代替直接访问这些成员。您可以定义u SILENCE u CXX17 u OLD u ALLOCATOR u MEMBERS u DEPRECATION u WARNING或u SILENCE u ALL u CXX17 u DEPRECATION u WARNINGS来确认您已收到此警告。”

“警告STL40.迭代器”:“警告STL4011:STD::RWYSturaGeEdter迭代器在C++ 17中被弃用。考虑使用STD::unInLaReZiDeActhCo()算法族。”您可以定义u SILENCE u CXX17 u RAW u STORAGE u ITERATOR u DEPRECATION u WARNING或u SILENCE u ALL u CXX17 u DEPRECATION u WARNINGS来确认您已收到此警告。”

在C++ 17中,警告STL4012:STD::GETYTimaAuthBuffer-()和STD::ReTrimeTimeAuthBuffer-()被定义为“C++”。

D.12[DEPR.meta类型]:“警告STL40:STD::ISS-文字类型和STD::ISS-文字类型V在C++ 17中被弃用。您可以定义SySalistyCx17IsLi文字类型,Debug,警告或SySnices,AxCx1717DePractIsIn警告,以确认您已经收到了这个警告。”

D.12[DEPR.meta类型]:“警告STL4014:STD::RESULTSO和STD::FultType of Fufft在C++ 17中被弃用。它们被STD::CuffKeRead结果和STD::CuffKeReultTytt取代。您可以定义u SILENCE u CXX17 u RESULT u OF u DEPRECATION u WARNING或u SILENCE u ALL u CXX17 u DEPRECATION u WARNINGS来确认您已收到此警告。”

D.13[DEPR迭代器。原语]:“警告STL4015:STD::迭代器类模板(用作基类提供Type Debug)在C++ 17中被禁止。(<迭代器>头不被禁止)。C++标准从来没有要求用户定义的迭代器从STD::要修复此警告,请停止从std::iterator派生,并开始提供名为iteratoru category、valueu type、differenceu type、pointer和reference的可公开访问的typedef。请注意,值类型必须是非常量,即使对于常量迭代器也是如此。您可以定义u SILENCE u CXX17 u ITERATOR u BASE u CLASS u DEPRECATION u WARNING或u SILENCE u ALL u CXX17 u DEPRECATION u WARNINGS来确认您已收到此警告。”

D.14[DeP.Upj.Studio.Stopy.OBS]:“警告STL4016:STD::SyrdYPPT:::UNIQUE())在C++ 17中被禁止。您可以定义“SySistNo.CX1717SyddPtRuxUngQueDePraceTraceId警告”或“SySnIsAyCX1717DePractIsTi警告”,以确认您已经收到了此警告。

D.15[depr.locale.stdcvt]和D.16[depr.conversions]:“警告STL4017:std::wbufferu convert,std::wstringu convert和头(包含std::codecvtu mode,std::codecvtu utf8,std::codecvtu utf16,而STD::CODECDVTUTUF8UTF16在C++ 17中被弃用。(STD::CODECDVT类模板不被禁止)。C++标准不提供等价的不可弃用的功能;考虑改用中的MultiByteToWideChar()和WideCharToMultiByte()。您可以定义u SILENCEu CXX17u codevtu HEADERu DEPRECATIONu WARNING或u SILENCEu ALLu CXX17u DEPRECATIONu WARNINGS来确认您已收到此警告。”

注意,对于所有的警告抑制宏,必须在包含任何C++标准库头(包括Vector >等和等)之前定义它们。这是因为我们用一个宏系统实现了弃用警告,当STL的中心内部头被拖入时,宏系统被初始化。因此,定义警告抑制宏的最佳位置是在命令行项目范围内,以确保在包含任何标题之前设置它们。如果需要定义多个宏,可以使用 /FI(名称强制包含文件)编译器选项 强制包含定义这些宏的头,这些宏将在源文件中的任何include指令之前处理。

库警告抑制

[[deprecated]]属性发出编译器警告C4996,可以为其提供自定义文本(正如您在上面所看到的,我们现在对STL的警告进行编号,以便于搜索。)

注: 由于C4996由所有的弃用警告(标准弃用和Microsoft弃用)共享,除非没有其他选择,否则应避免全局禁用它。例如,静默“warning C4996:’std::copy::u Uncheckedu iterators::u Deprecate”:使用可能不安全的参数调用“std::copy”-此调用依赖于调用方检查传递的值是否正确。要禁用此警告,请使用-Du SCLu SECUREu NOu WARNINGS。有关如何使用VisualC++的“检查迭代器”的文档,应该通过所提到的细粒度宏来完成,而不是通过/WD499传递给编译器(这也会抑制C++ 17的警告警告)。

然而,库代码有时需要做一些会触发不推荐使用警告的事情,即使它实际上不应该算作使用了不推荐使用的技术。这发生在STL本身中。例如,分配器需要询问UserAlloc::pointer是否存在(如果不存在则提供回退)。UserAlloc可能从STD:派生器提供了C++ 17不推荐的“指针”TyPulf。虽然从std::allocator派生不是一个好主意,但它可以一致地完成。将这样一个派生类赋给分配器不应该触发“std::allocator::pointer is deprecated”警告,因为程序员用户甚至没有提到typedef。

因此,在检查像这样的嵌套typedef的类型时,我们在本地抑制警告C4996,如下所示:

#pragma警告(推送)

#pragma警告(禁用:4996)    // 已声明为已弃用

模板

结构获取指针类型无效类型名称::指针>>

{    // 获取指针

使用type=typenameu Ty::pointer;

};

#pragma警告(pop)

虽然应该谨慎使用这种技术,但这就是第三个库如何避免触发弃用警告,而不要求程序员用户在整个项目中使它们保持沉默。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享