VS 2015中的STL修复,第2部分

除了实施 一大堆特征 在VS 2015的C++标准库中,我们也修复了一堆错误。  一年前,我列出了 VS 2015 CTP1中的STL修复 .  现在,是时候列出CTP1和RTM之间的STL修复了。 <功能>检修 我们最初将bind()/function/memu fn()/referenceu wrapper/等作为VS2008SP1中TR1的一部分提供。  当Tr1演化成C++ 0x,然后进入C++ 11时,我们更新了我们的实现,使用了rValk引用、DeCype和VALIDAY模板。  虽然这基本上是可行的,但TR1时代的机器极其复杂,多年来积累了大量的bug。  我们不希望标准库“大部分工作”—我们希望水晶般的完美。  因此,我几乎完全从头写了函数>,只保留C++ 03的东西和STD::For函数的骨架。  这大大减少了STL源代码的大小(24kb,935行编辑器)。  除了一个限制(Expression SFINAE in function/result of),大修修复了所有已知的错误: *在某些情况下,bind()不会使用从基类(DevDiv#617421)继承operator()的函数对象进行编译/ 连接#779061 ). *bind()没有完全转发通过占位符传递的未绑定参数,如#1(DevDiv#3411)/ 连接#717188 第410033页/ 连接#737872 第862588页/ 接#814028 ). *bind()的函数调用运算符没有const重载(DevDiv#535246/ 连接#773565 ,德夫迪夫#1034816/ 接#981289 ).  我最初的修复程序不小心尝试使用表达式SFINAE,但是我能够为RTM(DevDiv#1160769,DevDiv#1165732)修复它/ 接#1298009 ). *bind()/function/etc.很难使用PMFs/PMDs(指向成员函数/数据的指针)。  这个标准指定bind()/function/etc.调用一个名为INVOKE()的虚构函数,这个函数做了一些神奇的事情( 编号4527 20.9.2[功能要求]/1)。  INVOKE()知道函数对象、PMFs和PMDs都需要不同的语法,并且知道如何将PMFs/PMDs与基/派生对象的引用/原始指针/智能指针一起使用。  在C++ 17中,这是一个可以直接调用的实际函数调用()。  我的大修实现了invoke(),完全遵循标准,因此修复了PMFs/PMDs(DevDiv#294051)的所有错误/ 接#694400 第477804页/ 接759806 第487679页/ 连接#763571 第505570页/ 接#768903 ,第505572页/ 连接#768899 ,德夫迪夫#789899/ 接#802299 ). *bind()和std::function存在一些空间效率低下的问题,这可能会导致时间效率的急剧下降。  有一个例子报告说,在std::函数中存储绑定函子在x86上运行良好,但在x64上几乎慢了10倍(DevDiv#490878)。  这是由于x64的较大指针超出了小型函子优化(SFO)的限制,以及bind()和std::function表示形式中意外的膨胀所触发的。  解决这个问题需要做几件事。  首先,我修改了std::函数的表示,消除了不必要的膨胀,并为SFO提供了更多的可用空间。  第二,我重新调整了SFO,它以前有一个非常小的限制。  这个限额是官方没有记载的,我们保留将来更改的权利,但我可以告诉你它是什么。  在VS 2015中,如果函数对象与基本的u字符串一样大或更小,我们将其视为“小”(因此可以避免动态内存分配)。  (詹姆斯·麦克内利斯提出了这个启发。)  由于小字符串优化,我们的基本u字符串相当大,因此这意味着函子可以存储多个整数/指针,同时保留在SFO中。  最后,作为STL范围内彻底检查使用压缩对的一部分,bind()压缩空functor(如无状态lambda或更小的值),std::function压缩空分配器(如std::allocator,默认值)。  这避免了将SFO的宝贵信息浪费在存储空类上。  随着所有这些变化,我们预计SFO将更频繁地被激活。  64位体系结构仍有可能将用户函子推到极限之外,但受影响的函子要少得多。 有一些小的限制,为了完整起见,我将提到这些限制。  首先,std::函数不会尝试使用有状态分配器优化空functor。  (这在实践中并不重要,因为有状态分配器必须刚好低于SFO的限制才能受到影响。)  其次,bind()不尝试优化绑定到零参数的有状态函子。  (这在实践中不太可能发生,因为绑定零参数的唯一原因是嵌套的bind()。  bind(pmf/pmd)不是原因,因为最好用memu fn()或无状态lambda编写。)  最后,bind()将绑定的参数存储在一个元组中,元组不会被压缩,因此绑定占位符或其他空参数将为每个参数支付1字节的费用。  (这没什么大不了的,因为有界函子的大小几乎不重要,除非它超过了SFO的极限,我们已经大大增加了这个极限。  我们将来可能会压缩元组。) *函数::swap()必须是noexcept。  为了实现这一点,我给了SFO一个额外的要求。  函子必须是小的,并且是不可移动的,为了激活SFO,函子的可构造性必须是真的。 *由于SFO的元编程方式(DevDiv#1174895),函数生成的对象/可执行文件比需要的要大。  我对此进行了修改,在x86上将人工测试用例的大小减少了12%,在x64上减少了30%。  Office团队报告了这一情况,修复程序将x64可执行文件的大小减少了9%(它们有许多std::函数)。 *存储move(F)需要构造函数(F),但我们正在复制它(DevDiv#759096)。  虽然我已经解决了这个问题,但是请注意,标准仍然要求F是可复制的,所以不能在std::function中只存储可移动的函子。  (通常,STL类有“按需”需求。  例如,list不要求T小于comparable,除非调用list::sort(),这要归功于模板的工作方式。  由于类型擦除,函数的行为不同。  当您从UserFunctor构造function时,std::函数需要在UserFunctor上生成所有可能被调用的操作,因为它的实际类型将通过虚拟函数的魔力被擦除,而不管整个程序最终是否需要这些操作。  因为std::function是可复制的,所以它必须要求UserFunctor是可复制的,而不管您是否实际复制了任何std::functions。) *函数现在需要接受具有非void返回类型的函子( 长荣2420 ,德夫迪夫#1010027/ 连接#949899 ).  如果函子返回任何东西,它将被忽略。 *对于某些类型(名称过长,如set),函数发出警告C4503“超过修饰名称长度,名称被截断”(DevDiv#1053579,DevDiv#1094949)/ 接352543 ).  这是非常烦人的,尽管它不影响运行时行为。  在VS2015的开发过程中,这个问题暂时变得更严重,而我正在重新编写std::函数以正确使用分配器。  我追踪了C4503的最终原因,并尽可能地减轻了它们,所以很难无意中触发。  (C4503不能完全避免与当前的名称损坏系统。  编译器团队将来可能会对此进行更改。) *引用包装器在定义结果类型的函数对象(DevDiv#794227)上有问题,尤其是同时是一元和二进制的函数对象(DevDiv#864867)。 *reference_wrapper在函数类型上有问题,比如reference_wrapper,其中get()和赋值无法编译(DevDiv#535636,DevDiv#868374)。 *reference_wrapper不适用于纯虚拟函数调用操作符(DevDiv#391117)/ 接#734305 第897806页/ 接#828696 ). * <函数>中的所有内容(除了EncRebug的IN C++ 11,移除的IN C++ 17的东西,如pTrIf())现在都尊重任意的调用约定,包括Y-VECtReCar,以及编译器选项来改变默认调用约定(/GD,/GR,/GV,/GZ)。  与Boost不同,它总是受支持的,因此不需要定义宏来启用它。  (德夫迪夫#553067/ 接#774720 第563620页/ 连接#775554 ,德夫迪夫#793009/ 接#804357 ) 打一次电话给你 我使用Vista+重写了callu once()及其相关的onceu标志 InitOnceExecuteOnce() 使用手写的XP回退。  这修复了所有已知的错误: *未按照标准(DevDiv#637433)的要求处理异常处决/ 接#781049 第1086953页/ 接#1038276 ). *onceŠflag的构造函数没有按照标准(DevDivŠ497946)的要求标记为constexpr。  (请注意,虽然在VS 2015 RTM中它被标记为constexpr,但它受到编译器错误DevDiv#1134662“constexpr构造函数正在发射动态初始值设定项”的影响,我们计划在2015 Update 1中修复该错误。) *callŠonce()以前使用全局锁,在某些情况下会导致挂起(DevDivŠ840791)/ 接#811192 ).  这个全局锁还阻止同时执行带有单独once标志的单独call#once()调用(DevDiv#1092852)。 *callu once()以前使用bind(),但它不应该这样做。  (bind()对于占位符、引用包装器和嵌套的bind()表达式有特殊的情况,这些表达式都不应该被callu once()特别处理。) *新的实施更有效。  我在我的dev box(4核8线程Sandy Bridge i7-26003.4ghz;server2008r2,Win7类)通过让8个线程使用空lambda敲打一个once-u标志。  为了让测试花费大约一秒钟的时间,对于VS2013,我需要每个线程重复1百万次,对于VS2015,我需要每个线程重复35百万次。  这使我能够非常精确地测量call_once()的开销。  (例如,如果8个线程每次执行1M调用需要1s的挂钟时间,那么我说每次调用需要1s/8M= 125纳秒。)  与2013年相比,我发现 VS 2015 x86速度提高了37.2倍 (212.0纳秒提高到5.7纳秒),以及 x64的速度提高了87.7倍 (306.9纳秒提高到3.5纳秒)。  我认为x86的5.7ns和x64的3.5ns之间的差异是由于x64基于表的零开销异常处理(我们需要一个try/catch块来传输异常,不能通过InitOnceExecuteOnce()横冲直撞)。 原子修复 *原子现在static断言T必须是可复制的(DevDiv#798735)/ 接#805015 ).  例如,原子将发出编译器错误。 *标准忘了这么说(由公开发行跟踪) 长荣2426 ),但是compareŠu交换函数族应该在执行原子操作之前从“expected”读取,而不是在执行原子操作之后(DevDivŠ1015776)。  这允许编写某些算法,例如操纵列表节点。 *共享ptr的原子交换函数族在某些情况下可能会死锁(DevDiv#1066589)/ 接#1004269 ).  除了其他微妙的正确性和性能问题外,我们还解决了这个问题。 *现在支持/clr编译器选项(DevDiv#1088751/ 接#1041602 ).  注意,第30条多线程头(等)仍然被阻塞;我们将在将来调查取消这一限制。 多线程修复(ConcRT删除) 我们重新实现了STL的多线程原语,以避免使用并发运行时(ConcRT)。  在当时(2012年),使用ConcRT是一个好主意,但事实证明,它带来的麻烦比它的价值还多。  现在我们直接使用windowsapi,它修复了许多bug。  (唯一的例外是ConcRT仍然用于XP目标,因此XP没有收到这些修复。) *在构造全局变量时使用互斥锁可能会挂起(DevDiv#789979/ 接#802344 第968936页/ 接#900741 ). *async()/mutex/etc.在替换操作符new/delete时会崩溃(DevDiv#943284/ 接#868994 ,德夫迪夫#1019418/ 接#962406 ). *timed_mutex::try_lock_for()/etc.内存泄漏(DevDiv#957609)/ 连接#886682 ). *条件变量未正确处理零超时(DevDiv#1082065/ 接#1029842 ). 多线程修复(其他) *在构造std::thread时,标准要求“如果[user’s callable object]的调用以未捕获的异常终止,则应调用std::terminate。”( 编号4527 30.3.1.2[螺纹.thread.constr]/5)。  我们以前使用try/catch强制实现了这一点,但是这使得调试变得困难(DevDiv#918396)/ 接#845184 ).  现在我们通过允许用户异常进入noexcept来实现这一点,noexcept对调试很友好。 *条件变量的谓词等待函数调用其谓词的频率太高(DevDiv#1114006/ 连接#1098841 ).  现在他们完全遵循标准。 *std::thread的构造函数没有使用仅可移动的参数(DevDiv 357755)进行编译/ 接#729886 第1079684页/ 接#1026715 ). *这个#线程::get#id()速度太慢了(DevDiv#1039430)。 *我们已经解决了所有的正确性问题 安东尼·威廉姆斯报道 (DevDiv#482769),除了“std::atomic<>类模板不能在没有默认构造函数的类型上使用”之外,该模板由公开发行版跟踪 长荣2334 .  还有几个性能问题有待研究。 *当main()退出后调用时(例如在全局析构函数中),thread::join()可能挂起(DevDiv#435439)/ 接#747145 ). *打包的_task::make_ready_at_thread_exit()在多次调用时可能挂起(DevDiv#803317)。 *对没有共享状态的打包的任务调用时,打包的任务::reset()崩溃(DevDiv#865726)。  现在它抛出futureu error,futureu errc::nou state符合标准要求。 *std::线程不能正确处理DLL;当线程仍在执行DLL中的代码时,可以卸载DLL(DevDiv#895753)。  这在Windows应用商店应用程序中尤其有问题。 *在VS 2015的开发过程中,timed_mutex/recursive_timed_mutex的try_lock_for()/try_lock_until()将以100%的速度旋转CPU内核(DevDiv#1114242)/ 连接#1099043 ).  它们已经被重写以正确阻止。 *超时时,条件变量的wait for()/etc.可能会起得稍早(DevDiv#1129370)。 文件系统修复 除了执行 N4100型 文件系统“V3”技术规范,我们修复了几个bug。  (注意,当我们提供TS的头和名称空间std::experimental::filesystem时,我们还提供旧头和名称空间std::tr2::sys,用于有限的back compat。) *当前的#path()getter以前忽略了失败(DevDiv#430113)。  我们现在根据情况抛出异常或报告错误代码。  (尤其是,Windows应用商店应用程序不支持此功能,因此它将在那里失败。) *path::generic_string()/etc.没有返回正斜杠(DevDiv#982173)/ 接#916517 ). *在文件系统库中使用编译器选项/Zc:wcharŠu t-会触发链接器错误(DevDiv#1004799)。  /Zc:wchar_t-是一个令人憎恶的,但我们勉强支持它。 *rename(“test.txt”,“test.txt”)必须是no操作,但我们正在删除文件(DevDiv#1066931)/ 接#1006361 ). *上一个ŠwriteŠtime()getter和setter将时间戳截断为整秒(DevDivŠ1075324)/ 接#1018797 ).  现在我们保留了Windows的100ns分辨率。 *文件系统库有“抛出器”如“bool createu directories(const path&)”和“非抛出器”如“bool createu directories(const path&,erroru code&)noexcept”。  一些非抛出器被错误地实现,调用抛出器时没有任何try/catch逻辑(DevDiv#1180290)/ 接#1385031 ).  这将导致异常猛烈地撞击noexcept并触发程序终止。  我们已经修复了所有已知的问题,让非投掷者呼叫其他非投掷者。  在一种情况下,抛出者是核心实现,而非抛出者将其包装在try/catch中。  (请注意,非抛出器调用抛出器的情况还有很多,但它们是无害的,因为在我们的实现中,所涉及的“抛出器”实际上不会失败。  我们可能会在将来重做这个,但是没有时间进行VS 2015 RTM,因为这实际上是最后一个签入的STL修复。) *copy_file(src_path,dest_path,copy_options::update_existing)(可选带有错误代码)是一个将src_path复制/覆盖到dest_path的请求,当且仅当src_path最近被修改时(即“较新的覆盖较旧的”)。  由于一个反向的时间戳测试,我们的实现认为updateu existing意味着“旧的覆盖新的”。 *上次写入时间(路径,代码)、全部删除(路径,代码)和临时目录路径(代码)的失败返回值不正确。 *remove u all()以前返回0或1。  现在它正确地返回删除的文件数。 可视化工具改进 *shared_ptr/weak_ptr的可视化工具现在显示存储在控制块(DevDiv#497336)中的原始指针。  例如,当sharedu ptr转换为sharedu ptr或sharedu ptr转换为sharedu ptr时,这一点很重要。  控制块记住原始的派生*或任何东西*。 *我们现在可视化异常ptr(DevDiv#716887)。  这需要卢卡斯·乔多斯基(Lukasz Chodorski)和埃里克·费维森(Eric Feiveson)实施的魔法定制机器。 *我们现在可以看到原子和原子旗(DevDiv#756373)/ 连接#796725 ). *reverseŠiterator的可视化工具在技术上是正确的,但总是令人困惑(DevDivŠ950042)/ 接#879130 ).  现在它有向量/数组/列表迭代器和原始指针的特殊情况。  另外,一般情况下,现在将“current”数据成员显示为“base()”(这是检索它的成员函数),并有一个合成子级解释“NOTE:*ri相当于*prev(ri.base())”。  这应该可以防止进一步的混淆。 *我们现在将递归互斥(DevDiv#992590)可视化/ 连接#926641 ). *我们现在想象未来和承诺(DevDiv#1014393)。 *我们现在将初始化器列表和chrono::duration可视化。 *树迭代器的可视化工具(map/multimap/set/multiset)现在可以检测结束迭代器。 <随机>修复 *mt19937ŠU 64应该采用64位种子,但它将它们截断为32位(DevDivŠ619912)/ 连接#779231 ). *分段线性分布的输出完全不正确(DevDiv#665556)/ 接#783628 ). *generateŠu canonical()的输出完全不正确(DevDivŠ844616)/ 接#811611 ). *二项分布的输出对于某些参数是不正确的,如(100,0.991)(DevDiv#940047,DevDiv#1188781)/ 接#1444620 ). *分布及其参数类型应该有匹配的构造函数,包括显式性,但有许多不同的构造函数(DevDiv#977224,DevDiv#1076782)/ 接#1021566 ). Iostream/Locale修复 *putŠtime()错误地将%%z(时区偏移量)视为%%z(时区名称/缩写)的同义词(DevDivŠ821666/ 接#808156 ).  这实际上是CRT的strftime()中的一个bug,由James McNellis修复。 *用iostream的操作符>>()分析浮点值的结果不准确(DevDiv#938627/ 接#866093 第961116页/ 接#890195 ).  我们已经大大提高了这里的正确性,虽然我们仍然得到一些角落的情况下错误的,并有显着的性能问题。  在下一个主要版本中,我们计划切换回CRT进行浮点解析,它已经过彻底的修改以获得完全的正确性(并且比iostream的单独代码路径快得多)。  请注意,在VS 2015中,根据标准的要求,stod()/to_string()系列已重写为使用CRT。 *我们修复了iostream的浮点和整数解析(DevDiv#900436)中的几个读取溢出/ 连接#829931 ,德夫迪夫#911845/ 接#840103 ). *当给定的输入完全由空字符组成时,collate::transform()会出现错误,在x86上引发异常,在x64上分配一个巨大的字符串(DevDiv#869525)/ 接#814337 ). *basic_istream::ignore(n,delim)将n与INT_MAX进行比较,而不是标准(DevDiv#964171)所要求的数值_limits::MAX()/ 接#894605 ).  这是一个行为问题,而不是表面问题(我们有32位int和64位streamsize)。 *时间#get::doŠgetŠyear()认为世界将在2035年结束(DevDivŠ640278)。  旧行为:

null
  • [0,135]解析为[1900,2035]
  • [1361899]设置故障位
  • [19002035]逐字分析
  • [2036,9999]设置故障位

新行为:

  • [0,68]解析为[2000,2068]
  • [69,99]解析为[1969,1999]
  • [1009999]逐字分析

*此外,时间u get::do u get u year()没有跟随 编号4527 22.4[locale.categories]/2“get()成员接受一个iosŠbase::iostate&argument,它们忽略了该参数的值,但在出现解析错误时设置为iosŠbase::failbit。”(DevDivŠ990695),因为它没有忽略传入的值。 *我们修复了影响英特尔编译器(DevDiv#879860)的内部Š纱线机制中的不一致/ 接#817221 ).  (之所以这样命名,是因为纱线类似于细绳,猫也喜欢纱线。) <系统错误>修复 *system_category()。默认的_error_condition()完全不正确,影响了system_category()(DevDiv#781294)的大多数使用/ 接#800821 ).  给定一个Windows错误代码,如果它的值恰好是一个有效的Posix错误代码值(但不一定是相同的含义-通常是完全不同的含义!),它将返回用genericu category()标记的值。  现在我们正在实施 编号4527 19.5.1.5[syserr.errcat.objects]/4正确:“如果参数ev对应于POSIX errno值posv,函数应返回erroru condition(posv,genericu category())。否则,函数将返回erroru condition(ev,systemu category())。对于任何给定的操作系统,构成通信的内容都没有明确说明。” *错误类别对象在不同的DLL/EX(DevDiv#666062、DevDiv#1095970)之间的行为不正常/ 接#1053790 ).  这里的悲惨故事很复杂。  例如,调用generic_category()应该返回对单个唯一对象的引用,而不管调用它的位置如何。 这通常是通过单独编译到STL的DLL(或静态库)来实现的。  但是,我们不能单独编译erroru category machinery,因为它有一个返回std::string的虚message(),其表示形式受u ITERATORu DEBUGu级别的影响。  因此,generic_category()只在头文件中实现,但这意味着不同的用户DLL最终会有不同的实例化,从而得到不同的对象。  (这也可能在用户的EXE和STL的DLL之间造成麻烦。)  我们解决了这个问题,以实现尽可能多的一致性。  我们已经教过错误类别,它的派生类,以及它的操作符==()/操作符!=()将所有generic_category()对象视为相等,即使它们位于不同DLL中的不同地址(对于标准中的其他错误类别对象也是如此)。  这是为了用户定义的错误类别对象不受影响而实现的。  我们唯一无法修复的是错误类别地址的直接比较(代码应该改用operator==())。 *systemu category().message()现在使用 格式化消息() 字符串化Windows错误代码(DevDiv#1101599/ 连接#1075847 ).  这为更多的错误代码提供了比我们以前使用的表更详细的消息。 容器修复 *map/set系列拒绝使用空lambda作为比较器(DevDiv#375529)/ 连接#727957 ).  这是一个STL范围内的问题示例—我们试图优化空的比较器/分配器等,但这样做不一致且不正确(例如,假设空对象必须是默认可构造的,这是错误的)。  unique u ptr和unordered u meow在从用户定义的删除程序/散列程序派生时也有问题(例如,unordered u meow可以像函子一样调用)。  我用空基类优化实现了一个压缩对,然后修改STL来使用它,从而解决了这个问题。  这个集中的压缩对正确地处理所有的事情——例如,它不采用默认的可构造类型,它尊重最终类,并且必须用作数据成员(防止出现唯一的ptr/无序的u meow问题)。  以下是更新内容的详尽列表:

  • 序列容器:deque,forwardu list,list,vector(空分配器)
  • 关联容器:map/etc(空比较器、空分配器)
  • 无序容器:无序的u映射/etc(空散列、空相等谓词、空分配器)
  • :bind()(空的可调用对象)
  • :函数(空分配器)
  • :sharedu ptr,allocateu shared()(空deleters,空分配器)
  • :唯一的u ptr(空删除器)
  • :基本u字符串(空分配器)

*压缩对大修还修复了一个编译器错误,当试图转换移动构造唯一的ptr与自定义删除(DevDiv#1076756)/ 接#1021477 ). *无序的喵喵的a.rehash(n)没有完全实现 编号4527 23.2.5[unord.req]的后置条件“a.bucket_count()>a.size()/a.max_load_factor()和a.bucket_count()>=n”(DevDiv#824596)。 *无序的u meow插入太频繁地调用相等谓词,这稍微损害了性能。 *向量的insert(constŠiterator,const T&)和insert(constŠiterator,sizeŠtype,const T&)是复制而不是移动元素(DevDivŠ824985)。 *list::sort()和forwardŠlist::sort()假定它们可以默认构造分配器,这是不保证的(DevDivŠ920385)。  我修复了这个问题,从零开始重写它们,所以它们现在不尝试分配任何内存。 *STL总是要求分配器是可分配的(DevDiv#1119194)/ 连接#1114355 ).  现在我们正确地跟踪了 编号4527 17.6.3.5[allocator.requirements]/4,当POCCA/POCMA/POCS为真时,要求分配器是可复制可分配/可移动可分配/可交换的。 “笨蛋!”,黑魔王嘶嘶地说。  “你已经进入了分配者的领域,在那里我掌握了所有事物的一生!”  然后他高喊着可怕的权力话语:“波卡,波卡,波卡……” 其他修复程序 *的search()急切地调用distance(),这对于比随机迭代器(DevDiv#1003120)弱的迭代器来说不是很友好/ 连接#940497 ).  现在我们有了随机迭代器和较弱迭代器的单独实现。 *stable#sort()执行了元素不需要容忍的自移动赋值(DevDiv#957501)/ 连接#886652 ). *regex_match()/regex_search()未正确设置m.prefix().matched/m.suffix().matched(DevDiv#903531)。 *basic#regex的复制构造函数不是线程安全的(DevDiv 358803)/ 连接#1253646 ). *is#u assignable不允许重载逗号运算符(DevDiv#938759)。 *是否可以复制返回的错误答案(DevDiv#807340)/ 接#806233 ,德夫迪夫#940515/ 连接#868824 ).  我们错误地将它实现为isu琐碎的u copyu可构造的同义词。  现在,isu琐碎的u copyable是用一个编译器钩子实现的,这个钩子被修复以返回正确的答案。 *现在提供正确的u16string/u32string typedef(DevDiv#1078492/ 接#1023646 ). *stod()家族通过抛出异常(DevDiv#1113936)错误处理INF/NAN输入/ 连接#1098595 ).  我们现在严格按照标准办事。 *位集的构造函数正在验证字符,但没有跟踪 编号4527 20.6.1[bitset.cons]/5精确(DevDiv#931383)。 *pair/tuple没有标准(DevDiv#961569)所要求的默认移动构造函数/ 接#891428 ). *STL现在允许使用32位时间,但是这个选项仍然是非常邪恶的(DevDiv#972321)/ 接#904065 ,德夫迪夫#1026777/ 接#972033 ). *选项u HAS u EXCEPTIONS=0未记录、未测试,并且不受Microsoft支持。  我们从纯瓷器的主要来源,并尽量不弄乱它。  根据我们的判断,我们偶尔愿意用这个选项来解决重大问题。  缺陷报告DevDivා1073766/ 接#1015473 观察到2015年对noexcept的支持发出了EH逻辑,即使对于u HAS u EXCEPTIONS=0。  我们选择修复此问题,因此2015年的u HAS u EXCEPTIONS=0将像2013年一样运行。 *由 实现constexpr ,我们修复了所有“missing constexpr”bug(DevDiv#961568/ 连接#891373 第1074023页/ 接#1015584 ,德夫迪夫#1148036/ 连接#1211985 ),只有极少量的异常正在被跟踪。 图书馆问题 在VS 2015 CTP1和RTM之间,我们实现了23个C++ 14/17库问题(这是标准本身的缺陷的修复):

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