diff --git a/src/landscape.cpp b/src/landscape.cpp index d1d6f0bb70..77e5d36dbe 100644 --- a/src/landscape.cpp +++ b/src/landscape.cpp @@ -786,8 +786,8 @@ CommandCost CmdClearArea(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 const Company *c = (flags & (DC_AUTO | DC_BANKRUPT)) ? nullptr : Company::GetIfValid(_current_company); int limit = (c == nullptr ? INT32_MAX : GB(c->clear_limit, 16, 16)); - TileIterator *iter = HasBit(p2, 0) ? (TileIterator *)new DiagonalTileIterator(tile, p1) : new OrthogonalTileIterator(tile, p1); - for (; *iter != INVALID_TILE; ++(*iter)) { + OrthogonalOrDiagonalTileIterator iter(tile, p1, HasBit(p2, 0)); + for (; *iter != INVALID_TILE; ++iter) { TileIndex t = *iter; CommandCost ret = DoCommand(t, 0, 0, flags & ~DC_EXEC, CMD_LANDSCAPE_CLEAR); if (ret.Failed()) { @@ -803,7 +803,6 @@ CommandCost CmdClearArea(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 money -= ret.GetCost(); if (ret.GetCost() > 0 && money < 0) { _additional_cash_required = ret.GetCost(); - delete iter; return cost; } DoCommand(t, 0, 0, flags, CMD_LANDSCAPE_CLEAR); @@ -823,7 +822,6 @@ CommandCost CmdClearArea(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 cost.AddCost(ret); } - delete iter; return had_success ? cost : last_error; } diff --git a/src/object_cmd.cpp b/src/object_cmd.cpp index ff82745842..288e086afb 100644 --- a/src/object_cmd.cpp +++ b/src/object_cmd.cpp @@ -473,8 +473,8 @@ CommandCost CmdPurchaseLandArea(TileIndex tile, DoCommandFlag flags, uint32 p1, const Company *c = Company::GetIfValid(_current_company); int limit = (c == nullptr ? INT32_MAX : GB(c->purchase_land_limit, 16, 16)); - TileIterator *iter = HasBit(p2, 0) ? (TileIterator *)new DiagonalTileIterator(tile, p1) : new OrthogonalTileIterator(tile, p1); - for (; *iter != INVALID_TILE; ++(*iter)) { + OrthogonalOrDiagonalTileIterator iter(tile, p1, HasBit(p2, 0)); + for (; *iter != INVALID_TILE; ++iter) { TileIndex t = *iter; CommandCost ret = DoCommand(t, OBJECT_OWNED_LAND, 0, flags & ~DC_EXEC, CMD_BUILD_OBJECT); if (ret.Failed()) { @@ -490,7 +490,6 @@ CommandCost CmdPurchaseLandArea(TileIndex tile, DoCommandFlag flags, uint32 p1, money -= ret.GetCost(); if (ret.GetCost() > 0 && money < 0) { _additional_cash_required = ret.GetCost(); - delete iter; return cost; } DoCommand(t, OBJECT_OWNED_LAND, 0, flags, CMD_BUILD_OBJECT); @@ -501,7 +500,6 @@ CommandCost CmdPurchaseLandArea(TileIndex tile, DoCommandFlag flags, uint32 p1, cost.AddCost(ret); } - delete iter; return had_success ? cost : last_error; } @@ -538,8 +536,8 @@ CommandCost CmdBuildObjectArea(TileIndex tile, DoCommandFlag flags, uint32 p1, u const Company *c = Company::GetIfValid(_current_company); int limit = (c == nullptr ? INT32_MAX : GB(c->build_object_limit, 16, 16)); - TileIterator *iter = HasBit(p2, 0) ? (TileIterator *)new DiagonalTileIterator(tile, p1) : new OrthogonalTileIterator(tile, p1); - for (; *iter != INVALID_TILE; ++(*iter)) { + OrthogonalOrDiagonalTileIterator iter(tile, p1, HasBit(p2, 0)); + for (; *iter != INVALID_TILE; ++iter) { TileIndex t = *iter; CommandCost ret = DoCommand(t, type, view, flags & ~DC_EXEC, CMD_BUILD_OBJECT); if (ret.Failed()) { @@ -555,7 +553,6 @@ CommandCost CmdBuildObjectArea(TileIndex tile, DoCommandFlag flags, uint32 p1, u money -= ret.GetCost(); if (ret.GetCost() > 0 && money < 0) { _additional_cash_required = ret.GetCost(); - delete iter; return cost; } DoCommand(t, type, view, flags, CMD_BUILD_OBJECT); @@ -566,7 +563,6 @@ CommandCost CmdBuildObjectArea(TileIndex tile, DoCommandFlag flags, uint32 p1, u cost.AddCost(ret); } - delete iter; return had_success ? cost : last_error; } diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index c3f41f259b..e9c71fe084 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -2411,8 +2411,8 @@ CommandCost CmdConvertRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 CommandCost error = CommandCost(STR_ERROR_NO_SUITABLE_RAILROAD_TRACK); // by default, there is no track to convert. bool found_convertible_track = false; // whether we actually did convert some track (see bug #7633) - std::unique_ptr iter(diagonal ? (TileIterator *)new DiagonalTileIterator(area_start, area_end) : new OrthogonalTileIterator(area_start, area_end)); - for (; (tile = *iter) != INVALID_TILE; ++(*iter)) { + OrthogonalOrDiagonalTileIterator iter(area_start, area_end, diagonal); + for (; (tile = *iter) != INVALID_TILE; ++iter) { TileType tt = GetTileType(tile); /* Check if there is any track on tile */ diff --git a/src/terraform_cmd.cpp b/src/terraform_cmd.cpp index 59a6e2eb21..1cd3fa57e4 100644 --- a/src/terraform_cmd.cpp +++ b/src/terraform_cmd.cpp @@ -371,8 +371,8 @@ CommandCost CmdLevelLand(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 int limit = (c == nullptr ? INT32_MAX : GB(c->terraform_limit, 16, 16)); if (limit == 0) return_cmd_error(STR_ERROR_TERRAFORM_LIMIT_REACHED); - TileIterator *iter = HasBit(p2, 0) ? (TileIterator *)new DiagonalTileIterator(tile, p1) : new OrthogonalTileIterator(tile, p1); - for (; *iter != INVALID_TILE; ++(*iter)) { + OrthogonalOrDiagonalTileIterator iter(tile, p1, HasBit(p2, 0)); + for (; *iter != INVALID_TILE; ++iter) { TileIndex t = *iter; uint curh = TileHeight(t); while (curh != h) { @@ -389,7 +389,6 @@ CommandCost CmdLevelLand(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 money -= ret.GetCost(); if (money < 0) { _additional_cash_required = ret.GetCost(); - delete iter; return cost; } DoCommand(t, SLOPE_N, (curh > h) ? 0 : 1, flags, CMD_TERRAFORM_LAND); @@ -413,6 +412,5 @@ CommandCost CmdLevelLand(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 if (limit <= 0) break; } - delete iter; return had_success ? cost : last_error; } diff --git a/src/terraform_gui.cpp b/src/terraform_gui.cpp index 8249ea180e..241d4f87c0 100644 --- a/src/terraform_gui.cpp +++ b/src/terraform_gui.cpp @@ -110,17 +110,11 @@ static bool IsQueryConfirmIndustryOrRailStationInArea(TileIndex start_tile, Tile { if (_settings_client.gui.demolish_confirm_mode == DCM_OFF) return false; - std::unique_ptr tile_iterator; - - if (diagonal) { - tile_iterator = std::make_unique(end_tile, start_tile); - } else { - tile_iterator = std::make_unique(end_tile, start_tile); - } + OrthogonalOrDiagonalTileIterator tile_iterator(end_tile, start_tile, diagonal); bool destroying_industry_or_station = false; - for (; *tile_iterator != INVALID_TILE; ++(*tile_iterator)) { + for (; *tile_iterator != INVALID_TILE; ++tile_iterator) { if ((_cheats.magic_bulldozer.value && IsTileType(*tile_iterator, MP_INDUSTRY)) || (_settings_client.gui.demolish_confirm_mode == DCM_INDUSTRY_RAIL_STATION && IsRailStationTile(*tile_iterator))) { destroying_industry_or_station = true; diff --git a/src/tilearea_type.h b/src/tilearea_type.h index dd6ef8d0c3..80aaba0dab 100644 --- a/src/tilearea_type.h +++ b/src/tilearea_type.h @@ -305,4 +305,56 @@ public: } }; +class OrthogonalOrDiagonalTileIterator { + union { + OrthogonalTileIterator ortho; + DiagonalTileIterator diag; + }; + bool diagonal; + +public: + + OrthogonalOrDiagonalTileIterator(TileIndex corner1, TileIndex corner2, bool diagonal) : diagonal(diagonal) + { + if (diagonal) { + new (&this->diag) DiagonalTileIterator(corner1, corner2); + } else { + new (&this->ortho) OrthogonalTileIterator(corner1, corner2); + } + } + + ~OrthogonalOrDiagonalTileIterator() + { + if (diagonal) { + this->diag.~DiagonalTileIterator(); + } else { + this->ortho.~OrthogonalTileIterator(); + } + } + + inline operator TileIndex () const + { + if (diagonal) { + return *(this->diag); + } else { + return *(this->ortho); + } + } + + inline TileIndex operator *() const + { + return (TileIndex) (*this); + } + + OrthogonalOrDiagonalTileIterator& operator ++() + { + if (diagonal) { + ++this->diag; + } else { + ++this->ortho; + } + return *this; + } +}; + #endif /* TILEAREA_TYPE_H */ diff --git a/src/water_cmd.cpp b/src/water_cmd.cpp index 4e9c3d7334..e30bc4fce5 100644 --- a/src/water_cmd.cpp +++ b/src/water_cmd.cpp @@ -476,8 +476,8 @@ CommandCost CmdBuildCanal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 CommandCost cost(EXPENSES_CONSTRUCTION); - std::unique_ptr iter(HasBit(p2, 2) ? (TileIterator *)new DiagonalTileIterator(tile, p1) : new OrthogonalTileIterator(tile, p1)); - for (; *iter != INVALID_TILE; ++(*iter)) { + OrthogonalOrDiagonalTileIterator iter(tile, p1, HasBit(p2, 2)); + for (; *iter != INVALID_TILE; ++iter) { TileIndex current_tile = *iter; CommandCost ret;