Overview
This permanently removes our non-Standard TR1 implementation, which was superseded by C++11.
Fixes#183.Fixes#1002. (AndDevCom-381099 / Microsoft-internalVSO-729899.)
Thestd::tr1 namespace mostly consisted of aliases for Standard machinery. For example,std::tr1::shared_ptr was just an alias forstd::shared_ptr. One member function was affected: in<array>, TR1array::assign() was superseded by Standardarray::fill(). The most significant differences were in<random>, where the old engines and distributions were superseded by ones with new names and superior interfaces. For example, TR1mersenne_twister anduniform_int were superseded by Standardmersenne_twister_engine anduniform_int_distribution.
Eliminating TR1 removes unnecessary complexity from this fiendishly complex library. For users, it removes ways to write non-portable code. For library implementers, it reduces our maintenance burden, making it easier for us to reason about the remaining Standard code. We've been working towards TR1 removal for a long time:
In Aug 2017, VS 2017 15.3 shipped, removing most of TR1's machinery by default in C++17 mode and later.
In Dec 2017, VS 2017 15.5 shipped a warning to users that "The non-Standardstd::tr1 namespace and TR1-only machinery are deprecated and will be REMOVED."
In May 2024, VS 2022 17.10 shipped#4284, which extended the deprecation warnings to the non-Standard TR1 engines and distributions in<random> that were also available in thestd namespace because they served as base classes for the Standard engines and distributions.
Very recently, my#5712 disconnected the Standard engines and distributions from their TR1 ancestors, making it possible to finally remove TR1. And now, the conclusion.
In addition to removing thestd::tr1 namespace, the oldarray member function, and the old engines and distributions lurking in thestd namespace, this makes two more significant simplifications possible. Because the old engines had a different interface, various algorithms had to accept either old or new engines. We can now drop that logic, always using the more efficient new interface. Also,subtract_with_carry_engine had a complicated implementation, which was previously tangled up with somewhat different TR1 engines that had been abandoned during Standardization. Following up on#5712, I can fuse another base class, and a traits class, away. (This is the bulk of the commits and complexity in this PR.)
Commits
- Require Standard URBGs, delete machinery for TR1 generators.
- Remove
_HAS_TR1_NAMESPACE. - Remove
_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING. - Remove
_SILENCE_TR1_RANDOM_DEPRECATION_WARNING. - Simplify test for removed non-Standard names.
- Drop
_Swc_baseoperator>>() andoperator<<(), and_Swc_traits::_Write().- They were unused by
subtract_with_carry_engine.
- Drop
_Swc_basemin() andmax(), and_Swc_traits::_Max.- They were unused by
subtract_with_carry_engine.
- Fuse
_Swc_baseoperator()() with strengthenednoexcept. - Fuse
_Swc_basediscard(). - Fuse
_Swc_baseoperator==().- We don't need to
static_cast when calling_Left._Equals(_Right).
- Fuse
_Swc_basedefault_seed. - Introduce and consistently use
_Mytraits in_Swc_base andsubtract_with_carry_engine to make fusion easier and avoid shadowing. - Fuse
_Swc_base_Write_full(). - Drop
_Swc_base default ctor and ctor/seed() from_Gen&. - Fuse
_Swc_base construction.- Avoid redundant seeding in
subtract_with_carry_engine(_Seed_seq&).
- Fuse
_Swc_baseseed(). - Finish fusing
_Swc_base.- Note that
_Setx and_Carry are now directlyprivate; they were previously inherited privately.
_Carry is now a direct data member.- Simplify
_Swc_traits::_Reset() as_Readcy is alwaysfalse. - Fuse
_Swc_traits_Cy and_Mod, avoiding shadowing in_Write_full()!- Also drop now-unused
_Mod_t and_Seed_t.
- Fuse
_Swc_traits_Write_full(). - Finish fusing
_Swc_traits._Reset() and_Reduce() are becoming non-static member functions.
- Fuse
_Reset() intoseed(). - Consistently use
%=.
subtract_with_carry_engine Representation
I verified thatsubtract_with_carry_engine's representation isn't being changed by removing_Swc_base inheritance. I checked 32-bit and 64-bit engines, on both x64 and x86. I compared against the MSVC Build Tools 14.50 Preview 1, so the differences here also include#5712's recent removal of TR1subtract_with_carry inheritance.
Click to expand test case and output:
Test Case
#include<print>#include<random>usingnamespacestd;structTest1 : ranlux24_base {};structTest2 : ranlux48_base {};intmain() {println("Arch: {}-bit; _MSVC_STL_UPDATE: {}",sizeof(void*) *8, _MSVC_STL_UPDATE);println("ranlux24_base: sizeof: {}; alignof: {}",sizeof(ranlux24_base),alignof(ranlux24_base));println("ranlux48_base: sizeof: {}; alignof: {}",sizeof(ranlux48_base),alignof(ranlux48_base));}C:\Temp>cl /EHsc /nologo /W4 /std:c++latest /MT /Od /d1reportSingleClassLayoutTest meow.cpp && meowmeow.cpp
Old x64
class Test1 size(200): +--- 0 | +--- (base class std::subtract_with_carry_engine<unsigned int,24,10,24>) 0 | | +--- (base class std::subtract_with_carry<unsigned int,16777216,10,24>) 0 | | | +--- (base class std::_Swc_base<unsigned int,10,24,struct std::_Swc_traits<unsigned int,16777216,24> >) 0 | | | | +--- (base class std::_Circ_buf<unsigned int,24>) 0 | | | | | _Idx 4 | | | | | _Ax | | | | +---196 | | | | _Carry | | | +--- | | +--- | +--- +---class Test2 size(208): +--- 0 | +--- (base class std::subtract_with_carry_engine<unsigned __int64,48,5,12>) 0 | | +--- (base class std::subtract_with_carry<unsigned __int64,281474976710656,5,12>) 0 | | | +--- (base class std::_Swc_base<unsigned __int64,5,12,struct std::_Swc_traits<unsigned __int64,281474976710656,12> >) 0 | | | | +--- (base class std::_Circ_buf<unsigned __int64,12>) 0 | | | | | _Idx | | | | | <alignment member> (size=4) 8 | | | | | _Ax | | | | +---200 | | | | _Carry | | | | <alignment member> (size=4) | | | +--- | | +--- | +--- +---Arch: 64-bit; _MSVC_STL_UPDATE: 202507ranlux24_base: sizeof: 200; alignof: 4ranlux48_base: sizeof: 208; alignof: 8
New x64
class Test1 size(200): +--- 0 | +--- (base class std::subtract_with_carry_engine<unsigned int,24,10,24>) 0 | | +--- (base class std::_Circ_buf<unsigned int,24>) 0 | | | _Idx 4 | | | _Ax | | +---196 | | _Carry | +--- +---class Test2 size(208): +--- 0 | +--- (base class std::subtract_with_carry_engine<unsigned __int64,48,5,12>) 0 | | +--- (base class std::_Circ_buf<unsigned __int64,12>) 0 | | | _Idx | | | <alignment member> (size=4) 8 | | | _Ax | | +---200 | | _Carry | | <alignment member> (size=4) | +--- +---Arch: 64-bit; _MSVC_STL_UPDATE: 202510ranlux24_base: sizeof: 200; alignof: 4ranlux48_base: sizeof: 208; alignof: 8
Old x86
class Test1 size(200): +--- 0 | +--- (base class std::subtract_with_carry_engine<unsigned int,24,10,24>) 0 | | +--- (base class std::subtract_with_carry<unsigned int,16777216,10,24>) 0 | | | +--- (base class std::_Swc_base<unsigned int,10,24,struct std::_Swc_traits<unsigned int,16777216,24> >) 0 | | | | +--- (base class std::_Circ_buf<unsigned int,24>) 0 | | | | | _Idx 4 | | | | | _Ax | | | | +---196 | | | | _Carry | | | +--- | | +--- | +--- +---class Test2 size(208): +--- 0 | +--- (base class std::subtract_with_carry_engine<unsigned __int64,48,5,12>) 0 | | +--- (base class std::subtract_with_carry<unsigned __int64,281474976710656,5,12>) 0 | | | +--- (base class std::_Swc_base<unsigned __int64,5,12,struct std::_Swc_traits<unsigned __int64,281474976710656,12> >) 0 | | | | +--- (base class std::_Circ_buf<unsigned __int64,12>) 0 | | | | | _Idx | | | | | <alignment member> (size=4) 8 | | | | | _Ax | | | | +---200 | | | | _Carry | | | | <alignment member> (size=4) | | | +--- | | +--- | +--- +---Arch: 32-bit; _MSVC_STL_UPDATE: 202507ranlux24_base: sizeof: 200; alignof: 4ranlux48_base: sizeof: 208; alignof: 8
New x86
class Test1 size(200): +--- 0 | +--- (base class std::subtract_with_carry_engine<unsigned int,24,10,24>) 0 | | +--- (base class std::_Circ_buf<unsigned int,24>) 0 | | | _Idx 4 | | | _Ax | | +---196 | | _Carry | +--- +---class Test2 size(208): +--- 0 | +--- (base class std::subtract_with_carry_engine<unsigned __int64,48,5,12>) 0 | | +--- (base class std::_Circ_buf<unsigned __int64,12>) 0 | | | _Idx | | | <alignment member> (size=4) 8 | | | _Ax | | +---200 | | _Carry | | <alignment member> (size=4) | +--- +---Arch: 32-bit; _MSVC_STL_UPDATE: 202510ranlux24_base: sizeof: 200; alignof: 4ranlux48_base: sizeof: 208; alignof: 8
Overview
This permanently removes our non-Standard TR1 implementation, which was superseded by C++11.
Fixes#183.Fixes#1002. (AndDevCom-381099 / Microsoft-internalVSO-729899.)
The
std::tr1namespace mostly consisted of aliases for Standard machinery. For example,std::tr1::shared_ptrwas just an alias forstd::shared_ptr. One member function was affected: in<array>, TR1array::assign()was superseded by Standardarray::fill(). The most significant differences were in<random>, where the old engines and distributions were superseded by ones with new names and superior interfaces. For example, TR1mersenne_twisteranduniform_intwere superseded by Standardmersenne_twister_engineanduniform_int_distribution.Eliminating TR1 removes unnecessary complexity from this fiendishly complex library. For users, it removes ways to write non-portable code. For library implementers, it reduces our maintenance burden, making it easier for us to reason about the remaining Standard code. We've been working towards TR1 removal for a long time:
In Aug 2017, VS 2017 15.3 shipped, removing most of TR1's machinery by default in C++17 mode and later.
In Dec 2017, VS 2017 15.5 shipped a warning to users that "The non-Standard
std::tr1namespace and TR1-only machinery are deprecated and will be REMOVED."In May 2024, VS 2022 17.10 shipped#4284, which extended the deprecation warnings to the non-Standard TR1 engines and distributions in
<random>that were also available in thestdnamespace because they served as base classes for the Standard engines and distributions.Very recently, my#5712 disconnected the Standard engines and distributions from their TR1 ancestors, making it possible to finally remove TR1. And now, the conclusion.
In addition to removing the
std::tr1namespace, the oldarraymember function, and the old engines and distributions lurking in thestdnamespace, this makes two more significant simplifications possible. Because the old engines had a different interface, various algorithms had to accept either old or new engines. We can now drop that logic, always using the more efficient new interface. Also,subtract_with_carry_enginehad a complicated implementation, which was previously tangled up with somewhat different TR1 engines that had been abandoned during Standardization. Following up on#5712, I can fuse another base class, and a traits class, away. (This is the bulk of the commits and complexity in this PR.)Commits
_HAS_TR1_NAMESPACE._SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING._SILENCE_TR1_RANDOM_DEPRECATION_WARNING._Swc_baseoperator>>()andoperator<<(), and_Swc_traits::_Write().subtract_with_carry_engine._Swc_basemin()andmax(), and_Swc_traits::_Max.subtract_with_carry_engine._Swc_baseoperator()()with strengthenednoexcept._Swc_basediscard()._Swc_baseoperator==().static_castwhen calling_Left._Equals(_Right)._Swc_basedefault_seed._Mytraitsin_Swc_baseandsubtract_with_carry_engineto make fusion easier and avoid shadowing._Swc_base_Write_full()._Swc_basedefault ctor and ctor/seed()from_Gen&._Swc_baseconstruction.subtract_with_carry_engine(_Seed_seq&)._Swc_baseseed()._Readcywas alwaysfalse._Swc_base._Setxand_Carryare now directlyprivate; they were previously inherited privately._Carryis now a direct data member._Swc_traits::_Reset()as_Readcyis alwaysfalse._Swc_traits_Cyand_Mod, avoiding shadowing in_Write_full()!_Mod_tand_Seed_t._Swc_traits_Write_full()._Swc_traits._Reset()and_Reduce()are becoming non-static member functions._Reset()intoseed().%=.subtract_with_carry_engineRepresentationI verified that
subtract_with_carry_engine's representation isn't being changed by removing_Swc_baseinheritance. I checked 32-bit and 64-bit engines, on both x64 and x86. I compared against the MSVC Build Tools 14.50 Preview 1, so the differences here also include#5712's recent removal of TR1subtract_with_carryinheritance.Click to expand test case and output:
Test Case
Old x64
New x64
Old x86
New x86