Correct rstl::prereserved_vector implementation

This commit is contained in:
Jack Andersen 2018-02-14 18:37:21 -10:00
parent 98518e7d44
commit b405f33ded
17 changed files with 478 additions and 499 deletions

View File

@ -22,8 +22,8 @@ struct PATH : BigDNA
struct Link : BigDNA
{
DECL_DNA
Value<atUint32> regionIdx;
Value<atUint32> nodeIdx;
Value<atUint32> regionIdx;
Value<float> width2d;
Value<float> oneOverWidth2d;
};

View File

@ -63,7 +63,7 @@ CPlayerState::CPlayerState()
: x188_staticIntf(5)
{
x0_24_alive = true;
x24_powerups.set_size(41);
x24_powerups.resize(41);
}
CPlayerState::CPlayerState(CBitStreamReader& stream)
@ -74,7 +74,7 @@ CPlayerState::CPlayerState(CBitStreamReader& stream)
xc_health.SetHP(*reinterpret_cast<float*>(&tmp));
x8_currentBeam = EBeamId(stream.ReadEncoded(CBitStreamReader::GetBitCount(5)));
x20_currentSuit = EPlayerSuit(stream.ReadEncoded(CBitStreamReader::GetBitCount(4)));
x24_powerups.set_size(41);
x24_powerups.resize(41);
for (u32 i = 0; i < x24_powerups.size(); ++i)
{
if (PowerUpMaxValues[i] == 0)

View File

@ -122,7 +122,7 @@ private:
EPlayerVisor x18_transitioningVisor = x14_currentVisor;
float x1c_visorTransitionFactor = 0.2f;
EPlayerSuit x20_currentSuit = EPlayerSuit::Power;
rstl::prereserved_vector<CPowerUp, 41> x24_powerups;
rstl::reserved_vector<CPowerUp, 41> x24_powerups;
rstl::reserved_vector<std::pair<CAssetId, float>, 846> x170_scanTimes;
std::pair<u32, u32> x180_scanCompletionRate = {};
CStaticInterference x188_staticIntf;

View File

@ -52,7 +52,7 @@ static const u16 SelectionSfxs[] =
};
CHudVisorBeamMenu::CHudVisorBeamMenu(CGuiFrame& baseHud, EHudVisorBeamMenu type,
const rstl::prereserved_vector<bool, 4>& enables)
const rstl::reserved_vector<bool, 4>& enables)
: x0_baseHud(baseHud), x4_type(type)
{
x14_24_visibleDebug = true;
@ -300,7 +300,7 @@ void CHudVisorBeamMenu::SetIsVisibleGame(bool v)
Update(0.f, true);
}
void CHudVisorBeamMenu::SetPlayerHas(const rstl::prereserved_vector<bool, 4>& enables)
void CHudVisorBeamMenu::SetPlayerHas(const rstl::reserved_vector<bool, 4>& enables)
{
for (int i=0 ; i<4 ; ++i)
{

View File

@ -59,11 +59,11 @@ private:
void UpdateMenuWidgetTransform(int, CGuiWidget& w, float);
public:
CHudVisorBeamMenu(CGuiFrame& baseHud, EHudVisorBeamMenu type,
const rstl::prereserved_vector<bool, 4>& enables);
const rstl::reserved_vector<bool, 4>& enables);
void Update(float dt, bool init);
void UpdateHudAlpha(float alpha);
void SetIsVisibleGame(bool v);
void SetPlayerHas(const rstl::prereserved_vector<bool, 4>& enables);
void SetPlayerHas(const rstl::reserved_vector<bool, 4>& enables);
void SetSelection(int, int, float);
};

View File

@ -51,12 +51,12 @@ CSamusHud::CSamusHud(CStateManager& stateMgr)
x274_loadedFrmeBaseHud->SetMaxAspect(1.78f);
x2a0_helmetIntf = std::make_unique<CHudHelmetInterface>(*x264_loadedFrmeHelmet);
rstl::prereserved_vector<bool, 4> hasVisors = BuildPlayerHasVisors(stateMgr);
rstl::reserved_vector<bool, 4> hasVisors = BuildPlayerHasVisors(stateMgr);
x2a4_visorMenu = std::make_unique<CHudVisorBeamMenu>(*x274_loadedFrmeBaseHud,
CHudVisorBeamMenu::EHudVisorBeamMenu::Visor,
hasVisors);
rstl::prereserved_vector<bool, 4> hasBeams = BuildPlayerHasBeams(stateMgr);
rstl::reserved_vector<bool, 4> hasBeams = BuildPlayerHasBeams(stateMgr);
x2a8_beamMenu = std::make_unique<CHudVisorBeamMenu>(*x274_loadedFrmeBaseHud,
CHudVisorBeamMenu::EHudVisorBeamMenu::Beam,
hasBeams);
@ -76,23 +76,23 @@ CSamusHud::~CSamusHud()
g_SamusHud = nullptr;
}
rstl::prereserved_vector<bool, 4> CSamusHud::BuildPlayerHasVisors(const CStateManager& mgr)
rstl::reserved_vector<bool, 4> CSamusHud::BuildPlayerHasVisors(const CStateManager& mgr)
{
rstl::prereserved_vector<bool, 4> ret;
ret[0] = mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::CombatVisor);
ret[1] = mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::XRayVisor);
ret[2] = mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::ScanVisor);
ret[3] = mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::ThermalVisor);
rstl::reserved_vector<bool, 4> ret;
ret.push_back(mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::CombatVisor));
ret.push_back(mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::XRayVisor));
ret.push_back(mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::ScanVisor));
ret.push_back(mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::ThermalVisor));
return ret;
}
rstl::prereserved_vector<bool, 4> CSamusHud::BuildPlayerHasBeams(const CStateManager& mgr)
rstl::reserved_vector<bool, 4> CSamusHud::BuildPlayerHasBeams(const CStateManager& mgr)
{
rstl::prereserved_vector<bool, 4> ret;
ret[0] = mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::PowerBeam);
ret[1] = mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::IceBeam);
ret[2] = mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::WaveBeam);
ret[3] = mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::PlasmaBeam);
rstl::reserved_vector<bool, 4> ret;
ret.push_back(mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::PowerBeam));
ret.push_back(mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::IceBeam));
ret.push_back(mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::WaveBeam));
ret.push_back(mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::PlasmaBeam));
return ret;
}

View File

@ -194,8 +194,8 @@ class CSamusHud
CCookieCutterDepthRandomStaticFilter m_cookieCutterStatic = { EFilterType::NoColor };
static CSamusHud* g_SamusHud;
static rstl::prereserved_vector<bool, 4> BuildPlayerHasVisors(const CStateManager& mgr);
static rstl::prereserved_vector<bool, 4> BuildPlayerHasBeams(const CStateManager& mgr);
static rstl::reserved_vector<bool, 4> BuildPlayerHasVisors(const CStateManager& mgr);
static rstl::reserved_vector<bool, 4> BuildPlayerHasBeams(const CStateManager& mgr);
void InitializeFrameGluePermanent(const CStateManager& mgr);
void InitializeFrameGlueMutable(const CStateManager& mgr);
void UninitializeFrameGlueMutable();

View File

@ -34,7 +34,7 @@ public:
u32 x80_ = 0;
u32 x84_ = -1;
u32 x88_seed1 = 99;
rstl::prereserved_vector<std::unique_ptr<CElementGen>, 4> x8c_thermalColdParticles;
rstl::reserved_vector<std::unique_ptr<CElementGen>, 4> x8c_thermalColdParticles;
s32 xb0_ = -1;
u32 xb4_seed2 = 99;
std::unique_ptr<CElementGen> xb8_;

View File

@ -1,3 +1,4 @@
#include <stdlib.h>
#include "CPathFindArea.hpp"
#include "IVParamObj.hpp"
#include "CToken.hpp"
@ -8,12 +9,12 @@ namespace urde
CPFAreaOctree::CPFAreaOctree(CMemoryInStream& in)
{
x0_isLeaf = in.readUint32Big();
for (int i=0 ; i<3 ; ++i)
x4_points[i] = in.readVec3fBig();
x4_aabb.readBoundingBoxBig(in);
x1c_center.readBig(in);
for (int i=0 ; i<8 ; ++i)
x28_children[i] = reinterpret_cast<CPFAreaOctree*>(in.readUint32Big());
x48_regionCount = in.readUint32Big();
x4c_regions = reinterpret_cast<CPFRegion**>(in.readUint32Big());
x48_regions.set_size(in.readUint32Big());
x48_regions.set_data(reinterpret_cast<CPFRegion**>(in.readUint32Big()));
}
void CPFAreaOctree::Fixup(CPFArea& area)
@ -21,9 +22,9 @@ void CPFAreaOctree::Fixup(CPFArea& area)
x0_isLeaf = x0_isLeaf != 0 ? 1 : 0;
if (x0_isLeaf)
{
if (!x48_regionCount)
if (x48_regions.empty())
return;
x4c_regions = &area.x160_octreeRegionLookup[reinterpret_cast<uintptr_t>(x4c_regions)];
x48_regions.set_data(&area.x160_octreeRegionLookup[reinterpret_cast<uintptr_t>(x48_regions.data())]);
return;
}
@ -36,6 +37,18 @@ void CPFAreaOctree::Fixup(CPFArea& area)
}
}
int CPFAreaOctree::GetChildIndex(const zeus::CVector3f& point) const
{
int idx = 0x0;
if (point.x > x1c_center.x)
idx = 0x1;
if (point.y > x1c_center.y)
idx |= 0x2;
if (point.z > x1c_center.z)
idx |= 0x4;
return idx;
}
CPFOpenList::CPFOpenList()
{
@ -75,12 +88,12 @@ CPFArea::CPFArea(std::unique_ptr<u8[]>&& buf, u32 len)
x10_.reserve(maxRegionNodes);
u32 numBitfieldWords = (numRegions * (numRegions - 1) / 2 + 31) / 32;
x168_connectionsA.reserve(numBitfieldWords);
x168_connectionsGround.reserve(numBitfieldWords);
for (u32 i=0 ; i<numBitfieldWords ; ++i)
x168_connectionsA.push_back(r.readUint32Big());
x170_connectionsB.reserve(numBitfieldWords);
x168_connectionsGround.push_back(r.readUint32Big());
x170_connectionsFlyers.reserve(numBitfieldWords);
for (u32 i=0 ; i<numBitfieldWords ; ++i)
x170_connectionsB.push_back(r.readUint32Big());
x170_connectionsFlyers.push_back(r.readUint32Big());
r.seek(((((numRegions * numRegions) + 31) / 32) - numBitfieldWords) * 2 * sizeof(u32));
@ -101,6 +114,28 @@ CPFArea::CPFArea(std::unique_ptr<u8[]>&& buf, u32 len)
node.Fixup(*this);
}
bool CPFArea::PathExists(const CPFRegion* r1, const CPFRegion* r2, u32 flags) const
{
if (r1 == r2 || (flags & 0x4) != 0)
return true;
u32 i1 = r1->GetIndex();
u32 i2 = r2->GetIndex();
if (i1 > i2)
std::swap(i1, i2);
u32 remRegions = u32(x150_regions.size()) - i1;
u32 remConnections = remRegions * (remRegions - 1) / 2;
u32 totalConnections = u32(x150_regions.size()) * (u32(x150_regions.size()) - 1) / 2;
u32 bit = totalConnections - remConnections + i2 - (i1 + 1);
auto d = std::div(bit, 32);
if ((flags & 0x2) != 0)
return ((x170_connectionsFlyers[d.quot] >> d.rem) & 0x1) == 0x1;
else
return ((x168_connectionsGround[d.quot] >> d.rem) & 0x1) == 0x1;
}
CFactoryFnReturn FPathFindAreaFactory(const urde::SObjectTag& tag,
std::unique_ptr<u8[]>&& in, u32 len,
const urde::CVParamTransfer& vparms,

View File

@ -25,16 +25,16 @@ public:
class CPFAreaOctree
{
u32 x0_isLeaf;
zeus::CVector3f x4_points[3];
zeus::CAABox x4_aabb;
zeus::CVector3f x1c_center;
CPFAreaOctree* x28_children[8];
u32 x48_regionCount;
CPFRegion** x4c_regions;
rstl::prereserved_vector<CPFRegion*> x48_regions;
public:
CPFAreaOctree(CMemoryInStream& in);
void Fixup(CPFArea& area);
void GetChildIndex(const zeus::CVector3f&) const;
int GetChildIndex(const zeus::CVector3f& point) const;
void GetRegionList(const zeus::CVector3f&) const;
//void GetRegionListList(rstl::reserved_vector<rstl::prereserved_vector<CPFRegion>, 32>, const zeus::CVector3f&, float);
void GetRegionListList(rstl::reserved_vector<rstl::prereserved_vector<CPFRegion*>*, 32>, const zeus::CVector3f&, float);
bool IsPointInPaddedAABox(const zeus::CVector3f&, float);
void Render();
};
@ -102,13 +102,16 @@ class CPFArea
CPFOpenList x78_;
u32 x138_;
//std::unique_ptr<u8[]> x13c_data;
/* Used to be prereserved_vectors backed by x13c_data
* This has been changed to meet storage requirements of
* modern systems */
std::vector<CPFNode> x140_nodes; // x140: count, x144: ptr
std::vector<CPFLink> x148_links; // x148: count, x14c: ptr
std::vector<CPFRegion> x150_regions; // x150: count, x154: ptr
std::vector<CPFAreaOctree> x158_octree; // x158: count, x15c: ptr
std::vector<CPFRegion*> x160_octreeRegionLookup; // x160: count, x164: ptr
std::vector<u32> x168_connectionsA; // x168: word_count, x16c: ptr
std::vector<u32> x170_connectionsB; // x170: word_count, x174: ptr
std::vector<u32> x168_connectionsGround; // x168: word_count, x16c: ptr
std::vector<u32> x170_connectionsFlyers; // x170: word_count, x174: ptr
std::vector<CPFRegionData> x178_regionDatas;
zeus::CTransform x188_transform;
public:
@ -129,6 +132,7 @@ public:
void FindRegions(rstl::reserved_vector<CPFRegion, 4>&, const zeus::CVector3f&, u32);
void FindClosestRegion(const zeus::CVector3f&, u32, float);
void FindClosestReachablePoint(rstl::reserved_vector<CPFRegion, 4>&, const zeus::CVector3f&, u32);
bool PathExists(const CPFRegion* r1, const CPFRegion* r2, u32 flags) const;
};

View File

@ -12,8 +12,8 @@ CPFNode::CPFNode(CMemoryInStream& in)
CPFLink::CPFLink(CMemoryInStream& in)
{
x0_region = in.readUint32Big();
x4_node = in.readUint32Big();
x0_node = in.readUint32Big();
x4_region = in.readUint32Big();
x8_2dWidth = in.readFloatBig();
xc_oo2dWidth = in.readFloatBig();
}
@ -48,4 +48,69 @@ void CPFRegion::Fixup(CPFArea& area, u32& maxRegionNodes)
maxRegionNodes = x0_numNodes;
}
zeus::CVector3f CPFRegion::FitThroughLink2d(const zeus::CVector3f& p1, const CPFLink& link,
const zeus::CVector3f& p2, float f1) const
{
CPFNode& node = x4_startNode[link.GetNode()];
CPFNode& nextNode = x4_startNode[(link.GetNode() + 1) % x0_numNodes];
zeus::CVector3f nodeDelta = nextNode.GetPos() - node.GetPos();
float t = 0.5f;
if (f1 < 0.5f * link.Get2dWidth())
{
zeus::CVector2f delta2d(nodeDelta.x, nodeDelta.y);
delta2d *= link.GetOO2dWidth();
zeus::CVector3f nodeToP1 = p1 - node.GetPos();
float f27 = nodeToP1.dot(node.GetNormal());
float f31 = delta2d.dot(zeus::CVector2f(nodeToP1.y, nodeToP1.y));
zeus::CVector3f nodeToP2 = p2 - node.GetPos();
float f26 = -nodeToP2.dot(node.GetNormal());
float f1b = delta2d.dot(zeus::CVector2f(nodeToP2.y, nodeToP2.y));
float f3 = f27 + f26;
if (f3 > FLT_EPSILON)
t = zeus::clamp(f1, 1.f / f3 * (f26 * f31 + f27 * f1b), link.Get2dWidth() - f1) * link.GetOO2dWidth();
}
return nodeDelta * t + node.GetPos();
}
zeus::CVector3f CPFRegion::FitThroughLink3d(const zeus::CVector3f& p1, const CPFLink& link,
float f1, const zeus::CVector3f& p2, float f2, float f3) const
{
CPFNode& node = x4_startNode[link.GetNode()];
CPFNode& nextNode = x4_startNode[(link.GetNode() + 1) % x0_numNodes];
zeus::CVector3f nodeDelta = nextNode.GetPos() - node.GetPos();
float f25 = (p1 - node.GetPos()).dot(node.GetNormal());
float f24 = (node.GetPos() - p2).dot(node.GetNormal());
float f23 = f25 + f24;
# if 0
if (f2 < 0.5f * link.Get2dWidth())
{
zeus::CVector2f delta2d(nodeDelta.x, nodeDelta.y);
delta2d *= link.GetOO2dWidth();
zeus::CVector3f nodeToP1 = p1 - node.GetPos();
float f29 = delta2d.dot(zeus::CVector2f(nodeToP1.y, nodeToP1.y));
zeus::CVector3f nodeToP2 = p2 - node.GetPos();
float f1b = delta2d.dot(zeus::CVector2f(nodeToP2.y, nodeToP2.y));
if (f23 > FLT_EPSILON)
{
zeus::clamp(f2, 1.f / f23 * f24 * f29 + f25 * f1b, link.Get2dWidth() - f2) * link.GetOO2dWidth();
}
}
#endif
zeus::CVector3f midPoint = nodeDelta * 0.5f + node.GetPos();
float z;
if (f3 < 0.5f * f1)
{
float minZ = f3 + midPoint.z;
z = 0.5f * (p1.z + p2.z);
if (f23 > FLT_EPSILON)
z = 1.f / f23 * (f24 * p1.z + f25 * p2.z);
z = zeus::clamp(minZ, z, f1 + midPoint.z - f3);
}
else
{
z = (p1.z + p2.z) * 0.5f;
}
return {midPoint.x, midPoint.y, z};
}
}

View File

@ -22,14 +22,14 @@ public:
class CPFLink
{
u32 x0_region;
u32 x4_node;
u32 x0_node;
u32 x4_region;
float x8_2dWidth;
float xc_oo2dWidth;
public:
CPFLink(CMemoryInStream& in);
u32 GetRegion() const { return x0_region; }
u32 GetNode() const { return x4_node; }
u32 GetNode() const { return x0_node; }
u32 GetRegion() const { return x4_region; }
float Get2dWidth() const { return x8_2dWidth; }
float GetOO2dWidth() const { return xc_oo2dWidth; }
};
@ -52,7 +52,7 @@ public:
CPFRegion(CMemoryInStream& in);
void SetData(CPFRegionData* data) { x4c_regionData = data; }
CPFRegionData* Data() const { return x4c_regionData; }
void GetIndex() const;
u32 GetIndex() const { return x24_regionIdx; }
float GetHeight() const { return x14_height; }
void GetPathLink() const {}
u32 GetNumLinks() const { return x8_numLinks; }
@ -72,8 +72,8 @@ public:
void SetLinkTo(s32);
void DropToGround(zeus::CVector3f&) const;
void GetLinkMidPoint(const CPFLink&);
void FitThroughLink2d(const zeus::CVector3f&, const CPFLink&, const zeus::CVector3f&, float) const;
void FitThroughLink3d(const zeus::CVector3f&, const CPFLink&, float, const zeus::CVector3f&, float, float) const;
zeus::CVector3f FitThroughLink2d(const zeus::CVector3f&, const CPFLink&, const zeus::CVector3f&, float) const;
zeus::CVector3f FitThroughLink3d(const zeus::CVector3f&, const CPFLink&, float, const zeus::CVector3f&, float, float) const;
void IsPointInsidePaddedAABox(const zeus::CVector3f&, float) const;
};
@ -81,12 +81,12 @@ class CPFRegionData
{
float x0_ = 0.f;
zeus::CVector3f x4_;
s32 x10_ = -1;
s32 x10_cookie = -1;
zeus::CVector3f x14_;
s32 x20_ = 0;
CPFRegion* x24_openLess = nullptr;
CPFRegion* x28_openMore = nullptr;
s32 x2c_ = 0;
s32 x2c_pathLink = 0;
public:
CPFRegionData() = default;
@ -95,16 +95,16 @@ public:
CPFRegion* GetOpenLess() const { return x24_openLess; }
CPFRegion* GetOpenMore() const { return x28_openMore; }
void GetCost();
void GetPathLink() const;
s32 GetPathLink() const { return x2c_pathLink; }
void SetPathLink(s32 l) { x2c_pathLink = l; }
void GetParent() const;
void Setup(CPFRegion*, float, float);
void SetBestPoint(const zeus::CVector3f&);
void SetBestPointDistanceSquared(float);
float GetBestPointDistanceSquared() const;
void SetPathLink(s32);
void SetCookie(s32);
zeus::CVector3f GetBestPoint() const;
void GetCookie() const;
void SetCookie(s32 c) { x10_cookie = c; }
s32 GetCookie() const { return x10_cookie; }
};
}

View File

@ -3,10 +3,17 @@
namespace urde
{
CPathFindSearch::CPathFindSearch(CPFArea* area, u32 w1, u32 w2, float f1, float f2)
: x0_area(area), xd0_f2(f2), xd4_f1(f1), xdc_w1(w1), xe0_w2(1u << w2)
CPathFindSearch::CPathFindSearch(CPFArea* area, u32 flags, u32 w2, float f1, float f2)
: x0_area(area), xd0_f2(f2), xd4_f1(f1), xdc_flags(flags), xe0_w2(1u << w2)
{
}
void CPathFindSearch::Search(const zeus::CVector3f& p1, const zeus::CVector3f& p2)
{
x4_.clear();
xc8_ = 0;
}
}

View File

@ -10,15 +10,16 @@ namespace urde
class CPathFindSearch
{
CPFArea* x0_area;
u32 x4_ = 0;
rstl::reserved_vector<zeus::CVector3f, 16> x4_;
u32 xc8_ = 0;
float xd0_f2;
float xd4_f1;
float xd8_ = 10.f;
u32 xdc_w1;
u32 xdc_flags; // 0x2: flyer, 0x4: path-always-exists
u32 xe0_w2;
public:
CPathFindSearch(CPFArea* area, u32 w1, u32 w2, float f1, float f2);
CPathFindSearch(CPFArea* area, u32 flags, u32 w2, float f1, float f2);
void Search(const zeus::CVector3f& p1, const zeus::CVector3f& p2);
};
}

View File

@ -142,7 +142,7 @@ void CScriptActorRotate::UpdateActors(bool next, CStateManager& mgr)
void CScriptActorRotate::UpdateSpiderBallWaypoints(CStateManager& mgr)
{
rstl::prereserved_vector<TUniqueId, 1024> waypointIds;
rstl::reserved_vector<TUniqueId, 1024> waypointIds;
CObjectList& objectList = mgr.GetAllObjectList();
for (CEntity* ent : objectList)
{

View File

@ -21,37 +21,17 @@ using optional_object = std::experimental::optional<T>;
/**
* @brief Base vector backed by statically-allocated array
*/
template <class T, size_t N>
template <class T>
class _reserved_vector_base
{
protected:
union alignas(T) storage_t
{
struct {} _dummy;
T _value;
storage_t() : _dummy() {}
~storage_t() {}
};
explicit _reserved_vector_base(size_t _init_sz) : x0_size(_init_sz) {}
size_t x0_size;
storage_t x4_data[N];
T& _value(std::ptrdiff_t idx) { return x4_data[idx]._value; }
const T& _value(std::ptrdiff_t idx) const { return x4_data[idx]._value; }
template <typename Tp>
static void destroy(Tp& t, std::enable_if_t<std::is_destructible<Tp>::value &&
!std::is_trivially_destructible<Tp>::value>* = 0) { t.Tp::~Tp(); }
template <typename Tp>
static void destroy(Tp& t, std::enable_if_t<!std::is_destructible<Tp>::value ||
std::is_trivially_destructible<Tp>::value>* = 0) {}
public:
class const_iterator
{
friend class _reserved_vector_base;
protected:
const T* m_val;
explicit const_iterator(const T* val) : m_val(val) {}
public:
explicit const_iterator(const T* val) : m_val(val) {}
using value_type = T;
using difference_type = std::ptrdiff_t;
using pointer = T*;
@ -81,8 +61,8 @@ public:
class iterator : public const_iterator
{
friend class _reserved_vector_base;
explicit iterator(T* val) : const_iterator(val) {}
public:
explicit iterator(T* val) : const_iterator(val) {}
T& operator*() const { return *const_cast<T*>(const_iterator::m_val); }
T* operator->() const { return const_cast<T*>(const_iterator::m_val); }
iterator& operator++() { ++const_iterator::m_val; return *this; }
@ -102,8 +82,8 @@ public:
friend class _reserved_vector_base;
protected:
const T* m_val;
explicit const_reverse_iterator(const T* val) : m_val(val) {}
public:
explicit const_reverse_iterator(const T* val) : m_val(val) {}
using value_type = T;
using difference_type = std::ptrdiff_t;
using pointer = T*;
@ -133,8 +113,8 @@ public:
class reverse_iterator : public const_reverse_iterator
{
friend class _reserved_vector_base;
explicit reverse_iterator(T* val) : const_reverse_iterator(val) {}
public:
explicit reverse_iterator(T* val) : const_reverse_iterator(val) {}
T& operator*() const { return *const_cast<T*>(const_reverse_iterator::m_val); }
T* operator->() const { return const_cast<T*>(const_reverse_iterator::m_val); }
reverse_iterator& operator++() { --const_reverse_iterator::m_val; return *this; }
@ -151,6 +131,265 @@ public:
T& operator[](std::ptrdiff_t i) const { return const_cast<T*>(const_reverse_iterator::m_val)[-i]; }
};
protected:
static iterator _const_cast_iterator(const const_iterator& it) { return iterator(const_cast<T*>(it.m_val)); }
};
/**
* @brief Vector backed by statically-allocated array with uninitialized storage
*/
template <class T, size_t N>
class reserved_vector : public _reserved_vector_base<T>
{
union alignas(T) storage_t
{
struct {} _dummy;
T _value;
storage_t() : _dummy() {}
~storage_t() {}
};
size_t x0_size;
storage_t x4_data[N];
T& _value(std::ptrdiff_t idx) { return x4_data[idx]._value; }
const T& _value(std::ptrdiff_t idx) const { return x4_data[idx]._value; }
template <typename Tp>
static void destroy(Tp& t, std::enable_if_t<std::is_destructible<Tp>::value &&
!std::is_trivially_destructible<Tp>::value>* = 0) { t.Tp::~Tp(); }
template <typename Tp>
static void destroy(Tp& t, std::enable_if_t<!std::is_destructible<Tp>::value ||
std::is_trivially_destructible<Tp>::value>* = 0) {}
public:
using base = _reserved_vector_base<T>;
using iterator = typename base::iterator;
using const_iterator = typename base::const_iterator;
using reverse_iterator = typename base::reverse_iterator;
using const_reverse_iterator = typename base::const_reverse_iterator;
reserved_vector() : x0_size(0) {}
reserved_vector(const reserved_vector& other) : x0_size(other.x0_size)
{
for (size_t i=0 ; i<x0_size ; ++i)
::new (static_cast<void*>(std::addressof(_value(i)))) T(other._value(i));
}
reserved_vector& operator=(const reserved_vector& other)
{
size_t i = 0;
if (other.x0_size > x0_size)
{
for (; i<x0_size ; ++i)
_value(i) = other._value(i);
for (; i<other.x0_size ; ++i)
::new (static_cast<void*>(std::addressof(_value(i)))) T(other._value(i));
}
else if (other.x0_size < x0_size)
{
for (; i<other.x0_size ; ++i)
_value(i) = other._value(i);
if (std::is_destructible<T>::value && !std::is_trivially_destructible<T>::value)
for (; i<x0_size ; ++i)
destroy(_value(i));
}
else
{
for (; i<other.x0_size ; ++i)
_value(i) = other._value(i);
}
x0_size = other.x0_size;
return *this;
}
reserved_vector(reserved_vector&& other) : x0_size(other.x0_size)
{
for (size_t i=0 ; i<x0_size ; ++i)
::new (static_cast<void*>(std::addressof(_value(i)))) T(std::forward<T>(other._value(i)));
}
reserved_vector& operator=(reserved_vector&& other)
{
size_t i = 0;
if (other.x0_size > x0_size)
{
for (; i<x0_size ; ++i)
_value(i) = std::forward<T>(other._value(i));
for (; i<other.x0_size ; ++i)
::new (static_cast<void*>(std::addressof(_value(i)))) T(std::forward<T>(other._value(i)));
}
else if (other.x0_size < x0_size)
{
for (; i<other.x0_size ; ++i)
_value(i) = std::forward<T>(other._value(i));
if (std::is_destructible<T>::value && !std::is_trivially_destructible<T>::value)
for (; i<x0_size ; ++i)
destroy(_value(i));
}
else
{
for (; i<other.x0_size ; ++i)
_value(i) = std::forward<T>(other._value(i));
}
x0_size = other.x0_size;
return *this;
}
~reserved_vector()
{
if (std::is_destructible<T>::value && !std::is_trivially_destructible<T>::value)
for (size_t i=0 ; i<x0_size ; ++i)
destroy(_value(i));
}
void push_back(const T& d)
{
#ifndef NDEBUG
if (x0_size == N)
Log.report(logvisor::Fatal, "push_back() called on full rstl::reserved_vector.");
#endif
::new (static_cast<void*>(std::addressof(_value(x0_size)))) T(d);
++x0_size;
}
void push_back(T&& d)
{
#ifndef NDEBUG
if (x0_size == N)
Log.report(logvisor::Fatal, "push_back() called on full rstl::reserved_vector.");
#endif
::new (static_cast<void*>(std::addressof(_value(x0_size)))) T(std::forward<T>(d));
++x0_size;
}
template<class... _Args>
void emplace_back(_Args&&... args)
{
#ifndef NDEBUG
if (x0_size == N)
Log.report(logvisor::Fatal, "emplace_back() called on full rstl::reserved_vector.");
#endif
::new (static_cast<void*>(std::addressof(_value(x0_size)))) T(std::forward<_Args>(args)...);
++x0_size;
}
void pop_back()
{
#ifndef NDEBUG
if (x0_size == 0)
Log.report(logvisor::Fatal, "pop_back() called on empty rstl::reserved_vector.");
#endif
--x0_size;
destroy(_value(x0_size));
}
iterator insert(const_iterator pos, const T& value)
{
#ifndef NDEBUG
if (x0_size == N)
Log.report(logvisor::Fatal, "insert() called on full rstl::reserved_vector.");
#endif
auto target_it = base::_const_cast_iterator(pos);
if (pos == cend())
{
::new (static_cast<void*>(std::addressof(_value(x0_size)))) T(value);
}
else
{
::new (static_cast<void*>(std::addressof(_value(x0_size))))
T(std::forward<T>(_value(x0_size - 1)));
for (auto it = end() - 1; it != target_it; --it)
*it = std::forward<T>(*(it - 1));
*target_it = value;
}
++x0_size;
return target_it;
}
iterator insert(const_iterator pos, T&& value)
{
#ifndef NDEBUG
if (x0_size == N)
Log.report(logvisor::Fatal, "insert() called on full rstl::reserved_vector.");
#endif
auto target_it = base::_const_cast_iterator(pos);
if (pos == cend())
{
::new (static_cast<void*>(std::addressof(_value(x0_size)))) T(std::forward<T>(value));
}
else
{
::new (static_cast<void*>(std::addressof(_value(x0_size))))
T(std::forward<T>(_value(x0_size - 1)));
for (auto it = end() - 1; it != target_it; --it)
*it = std::forward<T>(*(it - 1));
*target_it = std::forward<T>(value);
}
++x0_size;
return target_it;
}
void resize(size_t size)
{
#ifndef NDEBUG
if (size > N)
Log.report(logvisor::Fatal, "resized() call overflows rstl::reserved_vector.");
#endif
if (size > x0_size)
{
for (size_t i = x0_size; i < size; ++i)
::new (static_cast<void*>(std::addressof(_value(i)))) T();
x0_size = size;
}
else if (size < x0_size)
{
if (std::is_destructible<T>::value && !std::is_trivially_destructible<T>::value)
for (size_t i = size; i < x0_size; ++i)
destroy(_value(i));
x0_size = size;
}
}
void resize(size_t size, const T& value)
{
#ifndef NDEBUG
if (size > N)
Log.report(logvisor::Fatal, "resized() call overflows rstl::reserved_vector.");
#endif
if (size > x0_size)
{
for (size_t i = x0_size; i < size; ++i)
::new (static_cast<void*>(std::addressof(_value(i)))) T(value);
x0_size = size;
}
else if (size < x0_size)
{
if (std::is_destructible<T>::value && !std::is_trivially_destructible<T>::value)
for (size_t i = size; i < x0_size; ++i)
destroy(_value(i));
x0_size = size;
}
}
iterator erase(const_iterator pos)
{
#ifndef NDEBUG
if (x0_size == 0)
Log.report(logvisor::Fatal, "erase() called on empty rstl::reserved_vector.");
#endif
for (auto it = base::_const_cast_iterator(pos) + 1; it != end(); ++it)
*(it - 1) = std::forward<T>(*it);
--x0_size;
destroy(_value(x0_size));
return base::_const_cast_iterator(pos);
}
void clear()
{
if (std::is_destructible<T>::value && !std::is_trivially_destructible<T>::value)
for (auto it = begin(); it != end(); ++it)
destroy(*it);
x0_size = 0;
}
size_t size() const noexcept { return x0_size; }
bool empty() const noexcept { return x0_size == 0; }
constexpr size_t capacity() const noexcept { return N; }
@ -179,430 +418,58 @@ public:
T& operator[](size_t idx) { return _value(idx); }
const T& operator[](size_t idx) const { return _value(idx); }
protected:
static iterator _const_cast_iterator(const const_iterator& it) { return iterator(const_cast<T*>(it.m_val)); }
};
/**
* @brief Vector backed by statically-allocated array with uninitialized storage
* @brief Vector-style view backed by externally-allocated storage
*/
template <class T, size_t N>
class reserved_vector : public _reserved_vector_base<T, N>
template <class T>
class prereserved_vector : public _reserved_vector_base<T>
{
size_t x0_size;
T* x4_data;
T& _value(std::ptrdiff_t idx) { return x4_data[idx]; }
const T& _value(std::ptrdiff_t idx) const { return x4_data[idx]; }
public:
using base = _reserved_vector_base<T, N>;
using base = _reserved_vector_base<T>;
using iterator = typename base::iterator;
using const_iterator = typename base::const_iterator;
reserved_vector() : base(0) {}
using reverse_iterator = typename base::reverse_iterator;
using const_reverse_iterator = typename base::const_reverse_iterator;
prereserved_vector() : x0_size(0), x4_data(nullptr) {}
prereserved_vector(size_t size, T* data) : x0_size(size), x4_data(data) {}
reserved_vector(const reserved_vector& other) : base(other.x0_size)
{
for (size_t i=0 ; i<base::x0_size ; ++i)
::new (static_cast<void*>(std::addressof(base::_value(i)))) T(other.base::_value(i));
}
void set_size(size_t n) { x0_size = n; }
void set_data(T* data) { x4_data = data; }
reserved_vector& operator=(const reserved_vector& other)
{
size_t i = 0;
if (other.base::x0_size > base::x0_size)
{
for (; i<base::x0_size ; ++i)
base::_value(i) = other.base::_value(i);
for (; i<other.base::x0_size ; ++i)
::new (static_cast<void*>(std::addressof(base::_value(i)))) T(other.base::_value(i));
}
else if (other.base::x0_size < base::x0_size)
{
for (; i<other.base::x0_size ; ++i)
base::_value(i) = other.base::_value(i);
if (std::is_destructible<T>::value && !std::is_trivially_destructible<T>::value)
for (; i<base::x0_size ; ++i)
base::destroy(base::_value(i));
}
else
{
for (; i<other.base::x0_size ; ++i)
base::_value(i) = other.base::_value(i);
}
base::x0_size = other.base::x0_size;
return *this;
}
size_t size() const noexcept { return x0_size; }
bool empty() const noexcept { return x0_size == 0; }
const T* data() const noexcept { return x4_data; }
T* data() noexcept { return x4_data; }
reserved_vector(reserved_vector&& other) : base(other.x0_size)
{
for (size_t i=0 ; i<base::x0_size ; ++i)
::new (static_cast<void*>(std::addressof(base::_value(i)))) T(std::forward<T>(other.base::_value(i)));
}
T& back() { return _value(x0_size - 1); }
T& front() { return _value(0); }
const T& back() const { return _value(x0_size - 1); }
const T& front() const { return _value(0); }
reserved_vector& operator=(reserved_vector&& other)
{
size_t i = 0;
if (other.base::x0_size > base::x0_size)
{
for (; i<base::x0_size ; ++i)
base::_value(i) = std::forward<T>(other.base::_value(i));
for (; i<other.base::x0_size ; ++i)
::new (static_cast<void*>(std::addressof(base::_value(i)))) T(std::forward<T>(other.base::_value(i)));
}
else if (other.base::x0_size < base::x0_size)
{
for (; i<other.base::x0_size ; ++i)
base::_value(i) = std::forward<T>(other.base::_value(i));
if (std::is_destructible<T>::value && !std::is_trivially_destructible<T>::value)
for (; i<base::x0_size ; ++i)
base::destroy(base::_value(i));
}
else
{
for (; i<other.base::x0_size ; ++i)
base::_value(i) = std::forward<T>(other.base::_value(i));
}
base::x0_size = other.base::x0_size;
return *this;
}
const_iterator begin() const noexcept { return const_iterator(std::addressof(_value(0))); }
const_iterator end() const noexcept { return const_iterator(std::addressof(_value(x0_size))); }
iterator begin() noexcept { return iterator(std::addressof(_value(0))); }
iterator end() noexcept { return iterator(std::addressof(_value(x0_size))); }
const_iterator cbegin() const noexcept { return begin(); }
const_iterator cend() const noexcept { return end(); }
~reserved_vector()
{
if (std::is_destructible<T>::value && !std::is_trivially_destructible<T>::value)
for (size_t i=0 ; i<base::x0_size ; ++i)
base::destroy(base::_value(i));
}
const_reverse_iterator rbegin() const noexcept
{ return const_reverse_iterator(std::addressof(_value(x0_size - 1))); }
const_reverse_iterator rend() const noexcept { return const_reverse_iterator(std::addressof(_value(-1))); }
reverse_iterator rbegin() noexcept { return reverse_iterator(std::addressof(_value(x0_size - 1))); }
reverse_iterator rend() noexcept { return reverse_iterator(std::addressof(_value(-1))); }
const_reverse_iterator crbegin() const noexcept { return rbegin(); }
const_reverse_iterator crend() const noexcept { return rend(); }
void push_back(const T& d)
{
#ifndef NDEBUG
if (base::x0_size == N)
Log.report(logvisor::Fatal, "push_back() called on full rstl::reserved_vector.");
#endif
::new (static_cast<void*>(std::addressof(base::_value(base::x0_size)))) T(d);
++base::x0_size;
}
void push_back(T&& d)
{
#ifndef NDEBUG
if (base::x0_size == N)
Log.report(logvisor::Fatal, "push_back() called on full rstl::reserved_vector.");
#endif
::new (static_cast<void*>(std::addressof(base::_value(base::x0_size)))) T(std::forward<T>(d));
++base::x0_size;
}
template<class... _Args>
void emplace_back(_Args&&... args)
{
#ifndef NDEBUG
if (base::x0_size == N)
Log.report(logvisor::Fatal, "emplace_back() called on full rstl::reserved_vector.");
#endif
::new (static_cast<void*>(std::addressof(base::_value(base::x0_size)))) T(std::forward<_Args>(args)...);
++base::x0_size;
}
void pop_back()
{
#ifndef NDEBUG
if (base::x0_size == 0)
Log.report(logvisor::Fatal, "pop_back() called on empty rstl::reserved_vector.");
#endif
--base::x0_size;
base::destroy(base::_value(base::x0_size));
}
iterator insert(const_iterator pos, const T& value)
{
#ifndef NDEBUG
if (base::x0_size == N)
Log.report(logvisor::Fatal, "insert() called on full rstl::reserved_vector.");
#endif
auto target_it = base::_const_cast_iterator(pos);
if (pos == base::cend())
{
::new (static_cast<void*>(std::addressof(base::_value(base::x0_size)))) T(value);
}
else
{
::new (static_cast<void*>(std::addressof(base::_value(base::x0_size))))
T(std::forward<T>(base::_value(base::x0_size - 1)));
for (auto it = base::end() - 1; it != target_it; --it)
*it = std::forward<T>(*(it - 1));
*target_it = value;
}
++base::x0_size;
return target_it;
}
iterator insert(const_iterator pos, T&& value)
{
#ifndef NDEBUG
if (base::x0_size == N)
Log.report(logvisor::Fatal, "insert() called on full rstl::reserved_vector.");
#endif
auto target_it = base::_const_cast_iterator(pos);
if (pos == base::cend())
{
::new (static_cast<void*>(std::addressof(base::_value(base::x0_size)))) T(std::forward<T>(value));
}
else
{
::new (static_cast<void*>(std::addressof(base::_value(base::x0_size))))
T(std::forward<T>(base::_value(base::x0_size - 1)));
for (auto it = base::end() - 1; it != target_it; --it)
*it = std::forward<T>(*(it - 1));
*target_it = std::forward<T>(value);
}
++base::x0_size;
return target_it;
}
void resize(size_t size)
{
#ifndef NDEBUG
if (size > N)
Log.report(logvisor::Fatal, "resized() call overflows rstl::reserved_vector.");
#endif
if (size > base::x0_size)
{
for (size_t i = base::x0_size; i < size; ++i)
::new (static_cast<void*>(std::addressof(base::_value(i)))) T();
base::x0_size = size;
}
else if (size < base::x0_size)
{
if (std::is_destructible<T>::value && !std::is_trivially_destructible<T>::value)
for (size_t i = size; i < base::x0_size; ++i)
base::destroy(base::_value(i));
base::x0_size = size;
}
}
void resize(size_t size, const T& value)
{
#ifndef NDEBUG
if (size > N)
Log.report(logvisor::Fatal, "resized() call overflows rstl::reserved_vector.");
#endif
if (size > base::x0_size)
{
for (size_t i = base::x0_size; i < size; ++i)
::new (static_cast<void*>(std::addressof(base::_value(i)))) T(value);
base::x0_size = size;
}
else if (size < base::x0_size)
{
if (std::is_destructible<T>::value && !std::is_trivially_destructible<T>::value)
for (size_t i = size; i < base::x0_size; ++i)
base::destroy(base::_value(i));
base::x0_size = size;
}
}
iterator erase(const_iterator pos)
{
#ifndef NDEBUG
if (base::x0_size == 0)
Log.report(logvisor::Fatal, "erase() called on empty rstl::reserved_vector.");
#endif
for (auto it = base::_const_cast_iterator(pos) + 1; it != base::end(); ++it)
*(it - 1) = std::forward<T>(*it);
--base::x0_size;
base::destroy(base::_value(base::x0_size));
return base::_const_cast_iterator(pos);
}
void clear()
{
if (std::is_destructible<T>::value && !std::is_trivially_destructible<T>::value)
for (auto it = base::begin(); it != base::end(); ++it)
base::destroy(*it);
base::x0_size = 0;
}
};
/**
* @brief Vector backed by statically-allocated array with default-initialized elements
*/
template <class T, size_t N>
class prereserved_vector : public _reserved_vector_base<T, N>
{
void _init()
{
for (auto& i : base::x4_data)
::new (static_cast<void*>(std::addressof(i._value))) T();
}
void _deinit()
{
if (std::is_destructible<T>::value && !std::is_trivially_destructible<T>::value)
for (auto& i : base::x4_data)
base::destroy(i._value);
}
public:
using base = _reserved_vector_base<T, N>;
using iterator = typename base::iterator;
using const_iterator = typename base::const_iterator;
prereserved_vector() : base(1) { _init(); }
prereserved_vector(const prereserved_vector& other) : base(other.x0_size)
{
for (size_t i=0 ; i<N ; ++i)
::new (static_cast<void*>(std::addressof(base::_value(i)))) T(other.base::_value(i));
}
prereserved_vector& operator=(const prereserved_vector& other)
{
for (size_t i=0 ; i<N ; ++i)
base::_value(i) = other.base::_value(i);
base::x0_size = other.base::x0_size;
return *this;
}
prereserved_vector(prereserved_vector&& other) : base(other.x0_size)
{
for (size_t i=0 ; i<N ; ++i)
::new (static_cast<void*>(std::addressof(base::_value(i)))) T(std::forward<T>(other.base::_value(i)));
}
prereserved_vector& operator=(prereserved_vector&& other)
{
for (size_t i=0 ; i<N ; ++i)
base::_value(i) = std::forward<T>(other.base::_value(i));
base::x0_size = other.base::x0_size;
return *this;
}
~prereserved_vector() { _deinit(); }
void set_size(size_t n)
{
if (n <= N)
base::x0_size = n;
}
void set_data(const T* data) { memmove(base::x4_data, data, sizeof(T) * base::x0_size); }
void push_back(const T& d)
{
#ifndef NDEBUG
if (base::x0_size == N)
Log.report(logvisor::Fatal, "push_back() called on full rstl::prereserved_vector.");
#endif
base::_value(base::x0_size) = d;
++base::x0_size;
}
void push_back(T&& d)
{
#ifndef NDEBUG
if (base::x0_size == N)
Log.report(logvisor::Fatal, "push_back() called on full rstl::prereserved_vector.");
#endif
base::_value(base::x0_size) = std::forward<T>(d);
++base::x0_size;
}
template<class... _Args>
void emplace_back(_Args&&... args)
{
#ifndef NDEBUG
if (base::x0_size == N)
Log.report(logvisor::Fatal, "emplace_back() called on full rstl::prereserved_vector.");
#endif
base::_value(base::x0_size) = T(std::forward<_Args>(args)...);
++base::x0_size;
}
void pop_back()
{
#ifndef NDEBUG
if (base::x0_size == 0)
Log.report(logvisor::Fatal, "pop_back() called on empty rstl::prereserved_vector.");
#endif
--base::x0_size;
}
iterator insert(const_iterator pos, const T& value)
{
#ifndef NDEBUG
if (base::x0_size == N)
Log.report(logvisor::Fatal, "insert() called on full rstl::reserved_vector.");
#endif
auto target_it = base::_const_cast_iterator(pos);
if (pos == base::cend())
{
*target_it = value;
}
else
{
for (auto it = base::end(); it != target_it; --it)
*it = std::forward<T>(*(it - 1));
*target_it = value;
}
++base::x0_size;
return target_it;
}
iterator insert(const_iterator pos, T&& value)
{
#ifndef NDEBUG
if (base::x0_size == N)
Log.report(logvisor::Fatal, "insert() called on full rstl::reserved_vector.");
#endif
auto target_it = base::_const_cast_iterator(pos);
if (pos == base::cend())
{
*target_it = std::forward<T>(value);
}
else
{
for (auto it = base::end(); it != target_it; --it)
*it = std::forward<T>(*(it - 1));
*target_it = std::forward<T>(value);
}
++base::x0_size;
return target_it;
}
void resize(size_t size)
{
#ifndef NDEBUG
if (size > N)
Log.report(logvisor::Fatal, "resized() call overflows rstl::prereserved_vector.");
#endif
base::x0_size = size;
}
void resize(size_t size, const T& value)
{
#ifndef NDEBUG
if (size > N)
Log.report(logvisor::Fatal, "resized() call overflows rstl::prereserved_vector.");
#endif
if (size > base::x0_size)
{
for (size_t i = base::x0_size; i < size; ++i)
base::_value(i) = T(value);
base::x0_size = size;
}
else if (size < base::x0_size)
{
base::x0_size = size;
}
}
iterator erase(const_iterator pos)
{
#ifndef NDEBUG
if (base::x0_size == 0)
Log.report(logvisor::Fatal, "erase() called on empty rstl::prereserved_vector.");
#endif
for (auto it = base::_const_cast_iterator(pos) + 1; it != base::end(); ++it)
*(it - 1) = std::forward<T>(*it);
--base::x0_size;
return base::_const_cast_iterator(pos);
}
void clear() { base::x0_size = 0; }
T& operator[](size_t idx) { return _value(idx); }
const T& operator[](size_t idx) const { return _value(idx); }
};
template<class ForwardIt, class T>

@ -1 +1 @@
Subproject commit f1d71e3e86f241ebd959b0a4e07f77913b34be63
Subproject commit 5c6e64c53f831b405e23dc2a105a16259dc5a076