pulling in latest

Signed-off-by: Scott Murray <scottmur@amazon.com>
monroegm-disable-blank-issue-2
Scott Murray 4 years ago
commit 5124a6322d

@ -162,11 +162,11 @@ def select_model_config(configname):
azlmbr.materialeditor.MaterialViewportRequestBus(azlmbr.bus.Broadcast, "SelectModelPresetByName", configname)
def destroy_main_window():
def exit():
"""
Closes the Material Editor window
Closes the Material Editor
"""
azlmbr.atomtools.AtomToolsMainWindowFactoryRequestBus(azlmbr.bus.Broadcast, "DestroyMainWindow")
azlmbr.atomtools.general.exit()
def wait_for_condition(function, timeout_in_seconds=1.0):

@ -214,7 +214,7 @@ def run():
(not material_editor.is_open(document1_id)) and
(not material_editor.is_open(document2_id)) and
(not material_editor.is_open(document3_id)), 2.0)
material_editor.destroy_main_window()
material_editor.exit()
if __name__ == "__main__":

@ -67,3 +67,6 @@ add_subdirectory(Multiplayer)
## Integration tests for editor testing framework ##
add_subdirectory(editor_test_testing)
## Performance ##
add_subdirectory(Performance)

@ -0,0 +1,39 @@
#
# Copyright (c) Contributors to the Open 3D Engine Project.
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
#
# SPDX-License-Identifier: Apache-2.0 OR MIT
#
#
if(NOT PAL_TRAIT_BUILD_TESTS_SUPPORTED OR NOT PAL_TRAIT_BUILD_HOST_TOOLS)
return()
endif()
ly_add_pytest(
NAME AutomatedTesting::EditorLevelLoadingPerfTests_DX12
TEST_SUITE periodic
TEST_REQUIRES gpu
TEST_SERIAL
PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Periodic_DX12.py
RUNTIME_DEPENDENCIES
Legacy::Editor
AZ::AssetProcessor
AutomatedTesting.Assets
COMPONENT
Performance
)
ly_add_pytest(
NAME AutomatedTesting::EditorLevelLoadingPerfTests_Vulkan
TEST_SUITE periodic
TEST_REQUIRES gpu
TEST_SERIAL
PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Periodic_Vulkan.py
RUNTIME_DEPENDENCIES
Legacy::Editor
AZ::AssetProcessor
AutomatedTesting.Assets
COMPONENT
Performance
)

@ -0,0 +1,31 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
# This suite consists of all test cases that are passing and have been verified.
import pytest
import os
import sys
from ly_test_tools.o3de.editor_test import EditorTestSuite, EditorSingleTest
@pytest.mark.parametrize("project", ["AutomatedTesting"])
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
class TestAutomation(EditorTestSuite):
class Time_EditorLevelLoading_10KEntityCpuPerfTest(EditorSingleTest):
extra_cmdline_args = ['-rhi=dx12']
use_null_renderer = False # needs renderer to validate test
from .tests import EditorLevelLoading_10KEntityCpuPerfTest as test_module
class Time_EditorLevelLoading_10kVegInstancesTest(EditorSingleTest):
extra_cmdline_args = ['-rhi=dx12']
use_null_renderer = False # needs renderer to validate test
from .tests import EditorLevelLoading_10kVegInstancesTest as test_module

@ -0,0 +1,34 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
# This suite consists of all test cases that are passing and have been verified.
import pytest
import os
import sys
from ly_test_tools.o3de.editor_test import EditorTestSuite, EditorSingleTest
@pytest.mark.parametrize("project", ["AutomatedTesting"])
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
class TestAutomation(EditorTestSuite):
class Time_EditorLevelLoading_10KEntityCpuPerfTest(EditorSingleTest):
# there is currently a huge discrepancy loading this level with vulkan compared to dx12 which requires the 10 min timeout
# this should be removed once that issue has been sorted out
timeout = 600
extra_cmdline_args = ['-rhi=vulkan']
use_null_renderer = False # needs renderer to validate test
from .tests import EditorLevelLoading_10KEntityCpuPerfTest as test_module
class Time_EditorLevelLoading_10kVegInstancesTest(EditorSingleTest):
extra_cmdline_args = ['-rhi=vulkan']
use_null_renderer = False # needs renderer to validate test
from .tests import EditorLevelLoading_10kVegInstancesTest as test_module

@ -0,0 +1,6 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
"""

@ -0,0 +1,15 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
from Performance.utils.perf_timer import time_editor_level_loading
def EditorLevelLoading_10KEntityCpuPerfTest():
time_editor_level_loading('Performance', '10KEntityCpuPerfTest')
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(EditorLevelLoading_10KEntityCpuPerfTest)

@ -0,0 +1,15 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
from Performance.utils.perf_timer import time_editor_level_loading
def EditorLevelLoading_10kVegInstancesTest():
time_editor_level_loading('Performance', '10kVegInstancesTest')
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(EditorLevelLoading_10kVegInstancesTest)

@ -0,0 +1,6 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
"""

@ -0,0 +1,6 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
"""

@ -0,0 +1,72 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
import time
ENTER_MSG = ("Entered game mode", "Failed to enter game mode")
EXIT_MSG = ("Exited game mode", "Couldn't exit game mode")
class Timer:
unit_divisor = 60
hour_divisor = unit_divisor * unit_divisor
def start(self):
self._start_time = time.perf_counter()
def log_time(self, message):
from editor_python_test_tools.utils import Report
elapsed_time = time.perf_counter() - self._start_time
hours = int(elapsed_time / Timer.hour_divisor)
minutes = int(elapsed_time % Timer.hour_divisor / Timer.unit_divisor)
seconds = elapsed_time % Timer.unit_divisor
Report.info(f'{message}: {hours:0>2d}:{minutes:0>2d}:{seconds:0>5.2f}\n')
def time_editor_level_loading(level_dir, level_name):
"""
Summary:
Time how long it takes to load an arbitrary level, entering game mode, and exiting game mode
Level Description:
Preferably a level with a large number of entities
Expected Behavior:
Level loads within a reasonable time frame e.i. doesn't trip the framework timeout
Benchmark Steps:
1) Time opening the level
2) Time entering game mode
3) Time exiting game mode
4) Close the editor
:return: None
"""
from editor_python_test_tools.utils import TestHelper as helper
timer = Timer()
helper.init_idle()
# 1) Open level
timer.start()
helper.open_level(level_dir, level_name)
timer.log_time('Level load time')
# 2) Time how long it takes to enter game mode
timer.start()
helper.enter_game_mode(ENTER_MSG)
timer.log_time('Enter game mode')
# 3) Exit game mode
timer.start()
helper.exit_game_mode(EXIT_MSG)
timer.log_time('Exit game mode')
# 4) Close the editor
helper.close_editor()

@ -38,7 +38,10 @@
},
"Component_[7874177159288365422]": {
"$type": "EditorEntitySortComponent",
"Id": 7874177159288365422
"Id": 7874177159288365422,
"Child Entity Order": [
"Entity_[471076350497]"
]
},
"Component_[8018146290632383969]": {
"$type": "EditorEntityIconComponent",
@ -110,34 +113,14 @@
"Component_[16871442125196328877]": {
"$type": "EditorEntitySortComponent",
"Id": 16871442125196328877,
"ChildEntityOrderEntryArray": [
{
"EntityId": "Entity_[604220336673]"
},
{
"EntityId": "Entity_[599925369377]",
"SortIndex": 1
},
{
"EntityId": "Entity_[475371317793]",
"SortIndex": 2
},
{
"EntityId": "Entity_[509731056161]",
"SortIndex": 3
},
{
"EntityId": "Entity_[505436088865]",
"SortIndex": 4
},
{
"EntityId": "Entity_[539795827233]",
"SortIndex": 5
},
{
"EntityId": "Entity_[569860598305]",
"SortIndex": 6
}
"Child Entity Order": [
"Entity_[604220336673]",
"Entity_[599925369377]",
"Entity_[475371317793]",
"Entity_[509731056161]",
"Entity_[505436088865]",
"Entity_[539795827233]",
"Entity_[569860598305]"
]
},
"Component_[18389136819207633744]": {
@ -263,10 +246,10 @@
"Configuration": {
"ModelAsset": {
"assetId": {
"guid": "{D0F73AAF-52B7-507C-B045-DBE2FE2D4403}",
"subId": 268677693
"guid": "{FD340C30-755C-5911-92A3-19A3F7A77931}",
"subId": 281415304
},
"assetHint": "objects/shaderball_simple/shaberball_simple_1m.azmodel"
"assetHint": "objects/shaderball/shaderball_default_1m.azmodel"
},
"LodOverride": 255
}
@ -370,10 +353,10 @@
"Configuration": {
"ModelAsset": {
"assetId": {
"guid": "{D0F73AAF-52B7-507C-B045-DBE2FE2D4403}",
"subId": 268677693
"guid": "{FD340C30-755C-5911-92A3-19A3F7A77931}",
"subId": 281415304
},
"assetHint": "objects/shaderball_simple/shaberball_simple_1m.azmodel"
"assetHint": "objects/shaderball/shaderball_default_1m.azmodel"
},
"LodOverride": 255
}
@ -477,10 +460,10 @@
"Configuration": {
"ModelAsset": {
"assetId": {
"guid": "{D0F73AAF-52B7-507C-B045-DBE2FE2D4403}",
"subId": 268677693
"guid": "{FD340C30-755C-5911-92A3-19A3F7A77931}",
"subId": 281415304
},
"assetHint": "objects/shaderball_simple/shaberball_simple_1m.azmodel"
"assetHint": "objects/shaderball/shaderball_default_1m.azmodel"
},
"LodOverride": 255
}
@ -584,10 +567,10 @@
"Configuration": {
"ModelAsset": {
"assetId": {
"guid": "{D0F73AAF-52B7-507C-B045-DBE2FE2D4403}",
"subId": 268677693
"guid": "{FD340C30-755C-5911-92A3-19A3F7A77931}",
"subId": 281415304
},
"assetHint": "objects/shaderball_simple/shaberball_simple_1m.azmodel"
"assetHint": "objects/shaderball/shaderball_default_1m.azmodel"
},
"LodOverride": 255
}
@ -691,10 +674,10 @@
"Configuration": {
"ModelAsset": {
"assetId": {
"guid": "{D0F73AAF-52B7-507C-B045-DBE2FE2D4403}",
"subId": 268677693
"guid": "{FD340C30-755C-5911-92A3-19A3F7A77931}",
"subId": 281415304
},
"assetHint": "objects/shaderball_simple/shaberball_simple_1m.azmodel"
"assetHint": "objects/shaderball/shaderball_default_1m.azmodel"
},
"LodOverride": 255
}
@ -798,10 +781,10 @@
"Configuration": {
"ModelAsset": {
"assetId": {
"guid": "{D0F73AAF-52B7-507C-B045-DBE2FE2D4403}",
"subId": 268677693
"guid": "{FD340C30-755C-5911-92A3-19A3F7A77931}",
"subId": 281415304
},
"assetHint": "objects/shaderball_simple/shaberball_simple_1m.azmodel"
"assetHint": "objects/shaderball/shaderball_default_1m.azmodel"
},
"LodOverride": 255
}
@ -905,10 +888,10 @@
"Configuration": {
"ModelAsset": {
"assetId": {
"guid": "{D0F73AAF-52B7-507C-B045-DBE2FE2D4403}",
"subId": 268677693
"guid": "{FD340C30-755C-5911-92A3-19A3F7A77931}",
"subId": 281415304
},
"assetHint": "objects/shaderball_simple/shaberball_simple_1m.azmodel"
"assetHint": "objects/shaderball/shaderball_default_1m.azmodel"
},
"LodOverride": 255
}
@ -944,30 +927,13 @@
"Component_[11056805018150955063]": {
"$type": "EditorEntitySortComponent",
"Id": 11056805018150955063,
"ChildEntityOrderEntryArray": [
{
"EntityId": "Entity_[488256219681]"
},
{
"EntityId": "Entity_[483961252385]",
"SortIndex": 1
},
{
"EntityId": "Entity_[479666285089]",
"SortIndex": 2
},
{
"EntityId": "Entity_[492551186977]",
"SortIndex": 3
},
{
"EntityId": "Entity_[496846154273]",
"SortIndex": 4
},
{
"EntityId": "Entity_[501141121569]",
"SortIndex": 5
}
"Child Entity Order": [
"Entity_[488256219681]",
"Entity_[483961252385]",
"Entity_[479666285089]",
"Entity_[492551186977]",
"Entity_[496846154273]",
"Entity_[501141121569]"
]
},
"Component_[11466054095979053511]": {
@ -1028,30 +994,13 @@
"Component_[11056805018150955063]": {
"$type": "EditorEntitySortComponent",
"Id": 11056805018150955063,
"ChildEntityOrderEntryArray": [
{
"EntityId": "Entity_[522615958049]"
},
{
"EntityId": "Entity_[518320990753]",
"SortIndex": 1
},
{
"EntityId": "Entity_[514026023457]",
"SortIndex": 2
},
{
"EntityId": "Entity_[526910925345]",
"SortIndex": 3
},
{
"EntityId": "Entity_[531205892641]",
"SortIndex": 4
},
{
"EntityId": "Entity_[535500859937]",
"SortIndex": 5
}
"Child Entity Order": [
"Entity_[522615958049]",
"Entity_[518320990753]",
"Entity_[514026023457]",
"Entity_[526910925345]",
"Entity_[531205892641]",
"Entity_[535500859937]"
]
},
"Component_[11466054095979053511]": {
@ -1180,10 +1129,10 @@
"Configuration": {
"ModelAsset": {
"assetId": {
"guid": "{D0F73AAF-52B7-507C-B045-DBE2FE2D4403}",
"subId": 268677693
"guid": "{FD340C30-755C-5911-92A3-19A3F7A77931}",
"subId": 281415304
},
"assetHint": "objects/shaderball_simple/shaberball_simple_1m.azmodel"
"assetHint": "objects/shaderball/shaderball_default_1m.azmodel"
},
"LodOverride": 255
}
@ -1287,10 +1236,10 @@
"Configuration": {
"ModelAsset": {
"assetId": {
"guid": "{D0F73AAF-52B7-507C-B045-DBE2FE2D4403}",
"subId": 268677693
"guid": "{FD340C30-755C-5911-92A3-19A3F7A77931}",
"subId": 281415304
},
"assetHint": "objects/shaderball_simple/shaberball_simple_1m.azmodel"
"assetHint": "objects/shaderball/shaderball_default_1m.azmodel"
},
"LodOverride": 255
}
@ -1394,10 +1343,10 @@
"Configuration": {
"ModelAsset": {
"assetId": {
"guid": "{D0F73AAF-52B7-507C-B045-DBE2FE2D4403}",
"subId": 268677693
"guid": "{FD340C30-755C-5911-92A3-19A3F7A77931}",
"subId": 281415304
},
"assetHint": "objects/shaderball_simple/shaberball_simple_1m.azmodel"
"assetHint": "objects/shaderball/shaderball_default_1m.azmodel"
},
"LodOverride": 255
}
@ -1501,10 +1450,10 @@
"Configuration": {
"ModelAsset": {
"assetId": {
"guid": "{D0F73AAF-52B7-507C-B045-DBE2FE2D4403}",
"subId": 268677693
"guid": "{FD340C30-755C-5911-92A3-19A3F7A77931}",
"subId": 281415304
},
"assetHint": "objects/shaderball_simple/shaberball_simple_1m.azmodel"
"assetHint": "objects/shaderball/shaderball_default_1m.azmodel"
},
"LodOverride": 255
}
@ -1608,10 +1557,10 @@
"Configuration": {
"ModelAsset": {
"assetId": {
"guid": "{D0F73AAF-52B7-507C-B045-DBE2FE2D4403}",
"subId": 268677693
"guid": "{FD340C30-755C-5911-92A3-19A3F7A77931}",
"subId": 281415304
},
"assetHint": "objects/shaderball_simple/shaberball_simple_1m.azmodel"
"assetHint": "objects/shaderball/shaderball_default_1m.azmodel"
},
"LodOverride": 255
}
@ -1715,10 +1664,10 @@
"Configuration": {
"ModelAsset": {
"assetId": {
"guid": "{D0F73AAF-52B7-507C-B045-DBE2FE2D4403}",
"subId": 268677693
"guid": "{FD340C30-755C-5911-92A3-19A3F7A77931}",
"subId": 281415304
},
"assetHint": "objects/shaderball_simple/shaberball_simple_1m.azmodel"
"assetHint": "objects/shaderball/shaderball_default_1m.azmodel"
},
"LodOverride": 255
}
@ -1754,30 +1703,13 @@
"Component_[11056805018150955063]": {
"$type": "EditorEntitySortComponent",
"Id": 11056805018150955063,
"ChildEntityOrderEntryArray": [
{
"EntityId": "Entity_[552680729121]"
},
{
"EntityId": "Entity_[548385761825]",
"SortIndex": 1
},
{
"EntityId": "Entity_[544090794529]",
"SortIndex": 2
},
{
"EntityId": "Entity_[556975696417]",
"SortIndex": 3
},
{
"EntityId": "Entity_[561270663713]",
"SortIndex": 4
},
{
"EntityId": "Entity_[565565631009]",
"SortIndex": 5
}
"Child Entity Order": [
"Entity_[552680729121]",
"Entity_[548385761825]",
"Entity_[544090794529]",
"Entity_[556975696417]",
"Entity_[561270663713]",
"Entity_[565565631009]"
]
},
"Component_[11466054095979053511]": {
@ -1906,10 +1838,10 @@
"Configuration": {
"ModelAsset": {
"assetId": {
"guid": "{D0F73AAF-52B7-507C-B045-DBE2FE2D4403}",
"subId": 268677693
"guid": "{FD340C30-755C-5911-92A3-19A3F7A77931}",
"subId": 281415304
},
"assetHint": "objects/shaderball_simple/shaberball_simple_1m.azmodel"
"assetHint": "objects/shaderball/shaderball_default_1m.azmodel"
},
"LodOverride": 255
}
@ -2013,10 +1945,10 @@
"Configuration": {
"ModelAsset": {
"assetId": {
"guid": "{D0F73AAF-52B7-507C-B045-DBE2FE2D4403}",
"subId": 268677693
"guid": "{FD340C30-755C-5911-92A3-19A3F7A77931}",
"subId": 281415304
},
"assetHint": "objects/shaderball_simple/shaberball_simple_1m.azmodel"
"assetHint": "objects/shaderball/shaderball_default_1m.azmodel"
},
"LodOverride": 255
}
@ -2120,10 +2052,10 @@
"Configuration": {
"ModelAsset": {
"assetId": {
"guid": "{D0F73AAF-52B7-507C-B045-DBE2FE2D4403}",
"subId": 268677693
"guid": "{FD340C30-755C-5911-92A3-19A3F7A77931}",
"subId": 281415304
},
"assetHint": "objects/shaderball_simple/shaberball_simple_1m.azmodel"
"assetHint": "objects/shaderball/shaderball_default_1m.azmodel"
},
"LodOverride": 255
}
@ -2227,10 +2159,10 @@
"Configuration": {
"ModelAsset": {
"assetId": {
"guid": "{D0F73AAF-52B7-507C-B045-DBE2FE2D4403}",
"subId": 268677693
"guid": "{FD340C30-755C-5911-92A3-19A3F7A77931}",
"subId": 281415304
},
"assetHint": "objects/shaderball_simple/shaberball_simple_1m.azmodel"
"assetHint": "objects/shaderball/shaderball_default_1m.azmodel"
},
"LodOverride": 255
}
@ -2334,10 +2266,10 @@
"Configuration": {
"ModelAsset": {
"assetId": {
"guid": "{D0F73AAF-52B7-507C-B045-DBE2FE2D4403}",
"subId": 268677693
"guid": "{FD340C30-755C-5911-92A3-19A3F7A77931}",
"subId": 281415304
},
"assetHint": "objects/shaderball_simple/shaberball_simple_1m.azmodel"
"assetHint": "objects/shaderball/shaderball_default_1m.azmodel"
},
"LodOverride": 255
}
@ -2441,10 +2373,10 @@
"Configuration": {
"ModelAsset": {
"assetId": {
"guid": "{D0F73AAF-52B7-507C-B045-DBE2FE2D4403}",
"subId": 268677693
"guid": "{FD340C30-755C-5911-92A3-19A3F7A77931}",
"subId": 281415304
},
"assetHint": "objects/shaderball_simple/shaberball_simple_1m.azmodel"
"assetHint": "objects/shaderball/shaderball_default_1m.azmodel"
},
"LodOverride": 255
}
@ -2480,30 +2412,13 @@
"Component_[11056805018150955063]": {
"$type": "EditorEntitySortComponent",
"Id": 11056805018150955063,
"ChildEntityOrderEntryArray": [
{
"EntityId": "Entity_[582745500193]"
},
{
"EntityId": "Entity_[578450532897]",
"SortIndex": 1
},
{
"EntityId": "Entity_[574155565601]",
"SortIndex": 2
},
{
"EntityId": "Entity_[587040467489]",
"SortIndex": 3
},
{
"EntityId": "Entity_[591335434785]",
"SortIndex": 4
},
{
"EntityId": "Entity_[595630402081]",
"SortIndex": 5
}
"Child Entity Order": [
"Entity_[582745500193]",
"Entity_[578450532897]",
"Entity_[574155565601]",
"Entity_[587040467489]",
"Entity_[591335434785]",
"Entity_[595630402081]"
]
},
"Component_[11466054095979053511]": {
@ -2632,10 +2547,10 @@
"Configuration": {
"ModelAsset": {
"assetId": {
"guid": "{D0F73AAF-52B7-507C-B045-DBE2FE2D4403}",
"subId": 268677693
"guid": "{FD340C30-755C-5911-92A3-19A3F7A77931}",
"subId": 281415304
},
"assetHint": "objects/shaderball_simple/shaberball_simple_1m.azmodel"
"assetHint": "objects/shaderball/shaderball_default_1m.azmodel"
},
"LodOverride": 255
}
@ -2739,10 +2654,10 @@
"Configuration": {
"ModelAsset": {
"assetId": {
"guid": "{D0F73AAF-52B7-507C-B045-DBE2FE2D4403}",
"subId": 268677693
"guid": "{FD340C30-755C-5911-92A3-19A3F7A77931}",
"subId": 281415304
},
"assetHint": "objects/shaderball_simple/shaberball_simple_1m.azmodel"
"assetHint": "objects/shaderball/shaderball_default_1m.azmodel"
},
"LodOverride": 255
}
@ -2846,10 +2761,10 @@
"Configuration": {
"ModelAsset": {
"assetId": {
"guid": "{D0F73AAF-52B7-507C-B045-DBE2FE2D4403}",
"subId": 268677693
"guid": "{FD340C30-755C-5911-92A3-19A3F7A77931}",
"subId": 281415304
},
"assetHint": "objects/shaderball_simple/shaberball_simple_1m.azmodel"
"assetHint": "objects/shaderball/shaderball_default_1m.azmodel"
},
"LodOverride": 255
}
@ -2953,10 +2868,10 @@
"Configuration": {
"ModelAsset": {
"assetId": {
"guid": "{D0F73AAF-52B7-507C-B045-DBE2FE2D4403}",
"subId": 268677693
"guid": "{FD340C30-755C-5911-92A3-19A3F7A77931}",
"subId": 281415304
},
"assetHint": "objects/shaderball_simple/shaberball_simple_1m.azmodel"
"assetHint": "objects/shaderball/shaderball_default_1m.azmodel"
},
"LodOverride": 255
}
@ -3060,10 +2975,10 @@
"Configuration": {
"ModelAsset": {
"assetId": {
"guid": "{D0F73AAF-52B7-507C-B045-DBE2FE2D4403}",
"subId": 268677693
"guid": "{FD340C30-755C-5911-92A3-19A3F7A77931}",
"subId": 281415304
},
"assetHint": "objects/shaderball_simple/shaberball_simple_1m.azmodel"
"assetHint": "objects/shaderball/shaderball_default_1m.azmodel"
},
"LodOverride": 255
}
@ -3167,10 +3082,10 @@
"Configuration": {
"ModelAsset": {
"assetId": {
"guid": "{D0F73AAF-52B7-507C-B045-DBE2FE2D4403}",
"subId": 268677693
"guid": "{FD340C30-755C-5911-92A3-19A3F7A77931}",
"subId": 281415304
},
"assetHint": "objects/shaderball_simple/shaberball_simple_1m.azmodel"
"assetHint": "objects/shaderball/shaderball_default_1m.azmodel"
},
"LodOverride": 255
}

@ -460,6 +460,33 @@
}
]
},
{
"Name": "DiffuseProbeGridVisualizationCompositePass",
"TemplateName": "DiffuseProbeGridVisualizationCompositePassTemplate",
"Connections": [
{
"LocalSlot": "VisualizationInput",
"AttachmentRef": {
"Pass": "OpaquePass",
"Attachment": "DiffuseProbeGridVisualization"
}
},
{
"LocalSlot": "Depth",
"AttachmentRef": {
"Pass": "DepthPrePass",
"Attachment": "Depth"
}
},
{
"LocalSlot": "ColorInputOutput",
"AttachmentRef": {
"Pass": "PostProcessPass",
"Attachment": "Output"
}
}
]
},
{
"Name": "AuxGeomPass",
"TemplateName": "AuxGeomPassTemplate",
@ -468,8 +495,8 @@
{
"LocalSlot": "ColorInputOutput",
"AttachmentRef": {
"Pass": "PostProcessPass",
"Attachment": "Output"
"Pass": "DiffuseProbeGridVisualizationCompositePass",
"Attachment": "ColorInputOutput"
}
},
{

@ -32,15 +32,6 @@
#include "Settings.h"
#include "CryEdit.h"
enum
{
// in milliseconds
GameModeIdleFrequency = 0,
EditorModeIdleFrequency = 1,
InactiveModeFrequency = 10,
UninitializedFrequency = 9999,
};
Q_LOGGING_CATEGORY(InputDebugging, "o3de.editor.input")
// internal, private namespace:
@ -234,18 +225,12 @@ namespace Editor
EditorQtApplication::EditorQtApplication(int& argc, char** argv)
: AzQtApplication(argc, argv)
, m_stylesheet(new AzQtComponents::O3DEStylesheet(this))
, m_idleTimer(new QTimer(this))
{
m_idleTimer->setInterval(UninitializedFrequency);
setWindowIcon(QIcon(":/Application/res/o3de_editor.ico"));
// set the default key store for our preferences:
setApplicationName("O3DE Editor");
connect(m_idleTimer, &QTimer::timeout, this, &EditorQtApplication::maybeProcessIdle);
connect(this, &QGuiApplication::applicationStateChanged, this, [this] { ResetIdleTimerInterval(PollState); });
installEventFilter(this);
// Disable our debugging input helpers by default
@ -324,6 +309,10 @@ namespace Editor
winapp->OnIdle(0);
}
}
if (m_applicationActive)
{
QTimer::singleShot(1, this, &EditorQtApplication::maybeProcessIdle);
}
}
void EditorQtApplication::InstallQtLogHandler()
@ -376,14 +365,6 @@ namespace Editor
case eNotify_OnQuit:
GetIEditor()->UnregisterNotifyListener(this);
break;
case eNotify_OnBeginGameMode:
// GetIEditor()->IsInGameMode() Isn't reliable when called from within the notification handler
ResetIdleTimerInterval(GameMode);
break;
case eNotify_OnEndGameMode:
ResetIdleTimerInterval(EditorMode);
break;
}
}
@ -456,55 +437,16 @@ namespace Editor
void EditorQtApplication::EnableOnIdle(bool enable)
{
m_applicationActive = enable;
if (enable)
{
if (m_idleTimer->interval() == UninitializedFrequency)
{
ResetIdleTimerInterval();
}
m_idleTimer->start();
}
else
{
m_idleTimer->stop();
QTimer::singleShot(0, this, &EditorQtApplication::maybeProcessIdle);
}
}
bool EditorQtApplication::OnIdleEnabled() const
{
if (m_idleTimer->interval() == UninitializedFrequency)
{
return false;
}
return m_idleTimer->isActive();
}
void EditorQtApplication::ResetIdleTimerInterval(TimerResetFlag flag)
{
bool isInGameMode = flag == GameMode;
if (flag == PollState)
{
isInGameMode = GetIEditor() ? GetIEditor()->IsInGameMode() : false;
}
// Game mode takes precedence over anything else
if (isInGameMode)
{
m_idleTimer->setInterval(GameModeIdleFrequency);
}
else
{
if (applicationState() & Qt::ApplicationActive)
{
m_idleTimer->setInterval(EditorModeIdleFrequency);
}
else
{
m_idleTimer->setInterval(InactiveModeFrequency);
}
}
return m_applicationActive;
}
bool EditorQtApplication::eventFilter(QObject* object, QEvent* event)

@ -102,13 +102,6 @@ namespace Editor
bool m_isMovingOrResizing = false;
private:
enum TimerResetFlag
{
PollState,
GameMode,
EditorMode
};
void ResetIdleTimerInterval(TimerResetFlag = PollState);
static QColor InterpolateColors(QColor a, QColor b, float factor);
void RefreshStyleSheet();
void InstallFilters();
@ -125,7 +118,6 @@ namespace Editor
QTranslator* m_editorTranslator = nullptr;
QTranslator* m_assetBrowserTranslator = nullptr;
QTimer* const m_idleTimer = nullptr;
AZ::UserSettingsProvider m_localUserSettings;
@ -133,5 +125,6 @@ namespace Editor
QSet<int> m_pressedKeys;
bool m_activatedLocalUserSettings = false;
bool m_applicationActive = false;
};
} // namespace editor

@ -135,7 +135,7 @@ namespace Editor
}
widget = widget->parentWidget();
}
return false;
return nullptr;
};
if (object == toolBarAt(QCursor::pos()))
{

@ -44,6 +44,9 @@ class CXTPDockingPaneLayout; // Needed for settings.h
#include <SceneAPI/SceneUI/SceneWidgets/SceneGraphInspectWidget.h>
#include <SceneAPI/SceneCore/Events/AssetImportRequest.h>
#include <SceneAPI/SceneCore/Utilities/Reporting.h>
#include <SceneAPI/SceneData/Rules/ScriptProcessorRule.h>
#include <SceneAPI/SceneCore/DataTypes/Rules/IScriptProcessorRule.h>
#include <SceneAPI/SceneCore/Containers/Utilities/Filters.h>
const char* AssetImporterWindow::s_documentationWebAddress = "http://docs.aws.amazon.com/lumberyard/latest/userguide/char-fbx-importer.html";
const AZ::Uuid AssetImporterWindow::s_browseTag = AZ::Uuid::CreateString("{C240D2E1-BFD2-4FFA-BB5B-CC0FA389A5D3}");
@ -198,7 +201,7 @@ void AssetImporterWindow::Init()
// Filling the initial browse prompt text to be programmatically set from available extensions
AZStd::unordered_set<AZStd::string> extensions;
EBUS_EVENT(AZ::SceneAPI::Events::AssetImportRequestBus, GetSupportedFileExtensions, extensions);
AZ_Assert(!extensions.empty(), "No file extensions defined for assets.");
AZ_Error(AZ::SceneAPI::Utilities::ErrorWindow, !extensions.empty(), "No file extensions defined for assets.");
if (!extensions.empty())
{
for (AZStd::string& extension : extensions)
@ -252,6 +255,7 @@ void AssetImporterWindow::OpenFileInternal(const AZStd::string& filePath)
[this, filePath]()
{
m_assetImporterDocument->LoadScene(filePath);
UpdateSceneDisplay({});
},
[this]()
{
@ -290,6 +294,11 @@ void AssetImporterWindow::UpdateClicked()
AZ_Assert(!m_processingOverlay, "Attempted to update asset while processing is in progress.");
return;
}
else if (!m_scriptProcessorRuleFilename.empty())
{
AZ_TracePrintf(AZ::SceneAPI::Utilities::WarningWindow, "A script updates the manifest; will not save.");
return;
}
m_processingOverlay.reset(new ProcessingOverlayWidget(m_overlay.data(), ProcessingOverlayWidget::Layout::Exporting, s_browseTag));
connect(m_processingOverlay.data(), &ProcessingOverlayWidget::Closing, this, &AssetImporterWindow::ClearProcessingOverlay);
@ -383,6 +392,18 @@ void AssetImporterWindow::OnSceneResetRequested()
m_rootDisplay->HandleSceneWasReset(m_assetImporterDocument->GetScene());
}, this);
// reset the script rule from the .assetinfo file if it exists
if (!m_scriptProcessorRuleFilename.empty())
{
m_scriptProcessorRuleFilename.clear();
if (QFile::exists(m_assetImporterDocument->GetScene()->GetManifestFilename().c_str()))
{
QFile file(m_assetImporterDocument->GetScene()->GetManifestFilename().c_str());
file.remove();
}
}
UpdateSceneDisplay({});
m_processingOverlay.reset(new ProcessingOverlayWidget(m_overlay.data(), ProcessingOverlayWidget::Layout::Resetting, s_browseTag));
m_processingOverlay->SetAndStartProcessingHandler(asyncLoadHandler);
m_processingOverlay->SetAutoCloseOnSuccess(true);
@ -390,6 +411,51 @@ void AssetImporterWindow::OnSceneResetRequested()
m_processingOverlayIndex = m_processingOverlay->PushToOverlay();
}
void AssetImporterWindow::OnAssignScript()
{
using namespace AZ::SceneAPI;
using namespace AZ::SceneAPI::Events;
using namespace AZ::SceneAPI::SceneUI;
using namespace AZ::SceneAPI::Utilities;
// use QFileDialog to select a Python script to embed into a scene manifest file
QString pyFilename = QFileDialog::getOpenFileName(this,
tr("Select scene builder Python script"),
Path::GetEditingGameDataFolder().c_str(),
tr("Python (*.py)"));
if (pyFilename.isNull())
{
return;
}
// reset the script rule from the .assetinfo file if it exists
if (!m_scriptProcessorRuleFilename.empty())
{
m_scriptProcessorRuleFilename.clear();
if (QFile::exists(m_assetImporterDocument->GetScene()->GetManifestFilename().c_str()))
{
QFile file(m_assetImporterDocument->GetScene()->GetManifestFilename().c_str());
file.remove();
}
}
// find the path relative to the project folder
pyFilename = Path::GetRelativePath(pyFilename, true);
// create a script rule
auto scriptProcessorRule = AZStd::make_shared<SceneData::ScriptProcessorRule>();
scriptProcessorRule->SetScriptFilename(pyFilename.toUtf8().toStdString().c_str());
// add the script rule to the manifest & save off the scene manifest
Containers::SceneManifest sceneManifest;
sceneManifest.AddEntry(scriptProcessorRule);
if (sceneManifest.SaveToFile(m_assetImporterDocument->GetScene()->GetManifestFilename()))
{
OpenFile(m_assetImporterDocument->GetScene()->GetSourceFilename());
}
}
void AssetImporterWindow::ResetMenuAccess(WindowState state)
{
if (state == WindowState::FileLoaded)
@ -480,7 +546,7 @@ void AssetImporterWindow::SetTitle(const char* filePath)
}
AZStd::string fileName;
AzFramework::StringFunc::Path::GetFileName(filePath, fileName);
converted->setWindowTitle(QString("%1 Settings (PREVIEW) - %2").arg(extension.c_str(), fileName.c_str()));
converted->setWindowTitle(QString("%1 Settings - %2").arg(extension.c_str(), fileName.c_str()));
break;
}
else
@ -490,6 +556,28 @@ void AssetImporterWindow::SetTitle(const char* filePath)
}
}
void AssetImporterWindow::UpdateSceneDisplay(const AZStd::shared_ptr<AZ::SceneAPI::Containers::Scene> scene) const
{
AZ::IO::FixedMaxPath projectPath = AZ::Utils::GetProjectPath();
AZ::IO::FixedMaxPath relativeSourcePath = AZ::IO::PathView(m_fullSourcePath).LexicallyProximate(projectPath);
auto sceneHeaderText = QString::fromUtf8(relativeSourcePath.c_str(), static_cast<int>(relativeSourcePath.Native().size()));
if (!m_scriptProcessorRuleFilename.empty())
{
sceneHeaderText.append("\n Assigned Python builder script (")
.append(m_scriptProcessorRuleFilename.c_str())
.append(")");
}
if (scene)
{
m_rootDisplay->SetSceneDisplay(sceneHeaderText, scene);
}
else
{
m_rootDisplay->SetSceneHeaderText(sceneHeaderText);
}
}
void AssetImporterWindow::HandleAssetLoadingCompleted()
{
if (!m_assetImporterDocument->GetScene())
@ -501,10 +589,24 @@ void AssetImporterWindow::HandleAssetLoadingCompleted()
m_fullSourcePath = m_assetImporterDocument->GetScene()->GetSourceFilename();
SetTitle(m_fullSourcePath.c_str());
AZ::IO::FixedMaxPath projectPath = AZ::Utils::GetProjectPath();
AZ::IO::FixedMaxPath relativeSourcePath = AZ::IO::PathView(m_fullSourcePath).LexicallyProximate(projectPath);
auto userFriendlyFileName = QString::fromUtf8(relativeSourcePath.c_str(), static_cast<int>(relativeSourcePath.Native().size()));
m_rootDisplay->SetSceneDisplay(userFriendlyFileName, m_assetImporterDocument->GetScene());
using namespace AZ::SceneAPI;
m_scriptProcessorRuleFilename.clear();
// load up the source scene manifest file
Containers::SceneManifest sceneManifest;
if (sceneManifest.LoadFromFile(m_assetImporterDocument->GetScene()->GetManifestFilename()))
{
// check a Python script rule is in that source manifest
auto view = Containers::MakeDerivedFilterView<DataTypes::IScriptProcessorRule>(sceneManifest.GetValueStorage());
if (!view.empty())
{
// record the info about the rule in the class
const auto scriptProcessorRule = &*view.begin();
m_scriptProcessorRuleFilename = scriptProcessorRule->GetScriptFilename();
}
}
UpdateSceneDisplay(m_assetImporterDocument->GetScene());
// Once we've browsed to something successfully, we need to hide the initial browse button layer and
// show the main area where all the actual work takes place

@ -47,6 +47,10 @@ namespace AZ
{
class ProcessingOverlayWidget;
}
namespace DataTypes
{
class IScriptProcessorRule;
}
}
}
@ -80,6 +84,7 @@ public:
public slots:
void OnSceneResetRequested();
void OnAssignScript();
void OnOpenDocumentation();
void OnInspect();
@ -105,6 +110,7 @@ private slots:
void OverlayLayerAdded();
void OverlayLayerRemoved();
void UpdateSceneDisplay(const AZStd::shared_ptr<AZ::SceneAPI::Containers::Scene> scene = {}) const;
private:
static const AZ::Uuid s_browseTag;
@ -122,4 +128,6 @@ private:
int m_processingOverlayIndex;
QSharedPointer<AZ::SceneAPI::SceneUI::ProcessingOverlayWidget> m_processingOverlay;
AZStd::string m_scriptProcessorRuleFilename;
};

@ -25,7 +25,8 @@
<string>&amp;Edit</string>
</property>
<addaction name="m_actionResetSettings"/>
</widget>
<addaction name="m_actionAssignScript"/>
</widget>
<widget class="QMenu" name="helpMenu">
<property name="title">
<string>&amp;Help</string>
@ -49,7 +50,7 @@
<enum>QLayout::SetMaximumSize</enum>
</property>
<!-- When an fbx is loaded -->
<!-- When a source scene file (i.e. FBX) is loaded -->
<item>
<widget class="QWidget" name="m_mainArea">
<property name="sizePolicy">
@ -175,7 +176,16 @@
<string>Reset the settings for this file (note: you will have to update to commit)</string>
</property>
</action>
<action name="m_actionAssignScript">
<property name="text">
<string>Assign Build Script...</string>
</property>
<property name="toolTip">
<string>Assign a Python build script that will override the scene's build rules</string>
</property>
</action>
<action name="actionOpenDocumentation">
<property name="text">
<string>Documentation</string>
@ -204,6 +214,12 @@
<receiver>AssetImporterWindow</receiver>
<slot>OnSceneResetRequested()</slot>
</connection>
<connection>
<sender>m_actionAssignScript</sender>
<signal>triggered()</signal>
<receiver>AssetImporterWindow</receiver>
<slot>OnAssignScript()</slot>
</connection>
<connection>
<sender>m_actionInspect</sender>
<signal>triggered()</signal>

@ -44,6 +44,11 @@ AZ::SceneAPI::UI::ManifestWidget* ImporterRootDisplay::GetManifestWidget()
return m_manifestWidget.data();
}
void ImporterRootDisplay::SetSceneHeaderText(const QString& headerText)
{
ui->m_filePathText->setText(headerText);
}
void ImporterRootDisplay::SetSceneDisplay(const QString& headerText, const AZStd::shared_ptr<AZ::SceneAPI::Containers::Scene>& scene)
{
AZ_PROFILE_FUNCTION(Editor);
@ -53,7 +58,7 @@ void ImporterRootDisplay::SetSceneDisplay(const QString& headerText, const AZStd
return;
}
ui->m_filePathText->setText(headerText);
SetSceneHeaderText(headerText);
HandleSceneWasReset(scene);

@ -63,6 +63,7 @@ public:
AZ::SceneAPI::UI::ManifestWidget* GetManifestWidget();
void SetSceneDisplay(const QString& headerText, const AZStd::shared_ptr<AZ::SceneAPI::Containers::Scene>& scene);
void SetSceneHeaderText(const QString& headerText);
void HandleSceneWasReset(const AZStd::shared_ptr<AZ::SceneAPI::Containers::Scene>& scene);
void HandleSaveWasSuccessful();
bool HasUnsavedChanges() const;

@ -40,7 +40,7 @@
</size>
</property>
<property name="styleSheet">
<string notr="true">#m_filePathText { margin: 2px; color: grey; }</string>
<string notr="true">#m_filePathText { margin: 2px; color: white; }</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>

@ -116,9 +116,6 @@ bool C3DConnexionDriver::GetInputMessageData(LPARAM lParam, S3DConnexionMessage&
{
if (event->header.dwType == RIM_TYPEHID)
{
static bool bGotTranslation = false,
bGotRotation = false;
static int all6DOFs[6] = {0};
LPRAWHID pRawHid = &event->data.hid;
// Translation or Rotation packet? They come in two different packets.

@ -709,7 +709,10 @@ namespace AZ::IO
constexpr reference operator*() const;
constexpr pointer operator->() const;
constexpr pointer operator->() const
{
return &m_stashed_elem;
}
constexpr PathIterator& operator++();

@ -1397,12 +1397,6 @@ namespace AZ::IO
return m_stashed_elem;
}
template <typename PathType>
constexpr auto PathIterator<PathType>::operator->() const -> pointer
{
return &m_stashed_elem;
}
template <typename PathType>
constexpr auto PathIterator<PathType>::operator++() -> PathIterator&
{
@ -1542,3 +1536,13 @@ namespace AZ::IO
extern template bool operator!=<const FixedMaxPath>(const PathIterator<const FixedMaxPath>& lhs,
const PathIterator<const FixedMaxPath>& rhs);
}
namespace AZStd::ranges
{
// A PathView is a borrowed range, it does not own the content of the Path it is viewing
template<>
inline constexpr bool enable_borrowed_range<AZ::IO::PathView> = true;
template<>
inline constexpr bool enable_view<AZ::IO::PathView> = true;
}

@ -13,6 +13,7 @@
#include <AzCore/Memory/OSAllocator.h> // required by certain platforms
#include <AzCore/std/parallel/mutex.h>
#include <AzCore/std/parallel/lock.h>
#include <AzCore/std/containers/intrusive_list.h>
#include <AzCore/std/containers/intrusive_set.h>
#ifdef _DEBUG
@ -41,8 +42,8 @@
#define HPPA_ASSERT_PRINT_STACK(...) _EXPAND(_GET_MACRO23(__VA_ARGS__, _HPPA_ASSERT_PRINT_STACK3, _HPPA_ASSERT_PRINT_STACK2)(__VA_ARGS__))
namespace AZ {
namespace AZ
{
/// default windows virtual page size \todo Read this from the OS when we create the allocator)
#define OS_VIRTUAL_PAGE_SIZE AZ_PAGE_SIZE
//////////////////////////////////////////////////////////////////////////
@ -56,211 +57,78 @@ namespace AZ {
// Enabled mutex per bucket
#define USE_MUTEX_PER_BUCKET
//////////////////////////////////////////////////////////////////////////
// TODO: Replace with AZStd::intrusive_list
class intrusive_list_base
{
public:
class node_base
{
node_base* mPrev;
node_base* mNext;
public:
node_base* next() const {return mNext; }
node_base* prev() const {return mPrev; }
void reset()
{
mPrev = this;
mNext = this;
}
void unlink()
{
mNext->mPrev = mPrev;
mPrev->mNext = mNext;
}
void link(node_base* node)
{
mPrev = node->mPrev;
mNext = node;
node->mPrev = this;
mPrev->mNext = this;
}
};
intrusive_list_base()
{
mHead.reset();
}
intrusive_list_base(const intrusive_list_base&)
{
mHead.reset();
}
bool empty() const {return mHead.next() == &mHead; }
void swap(intrusive_list_base& other)
{
node_base* node = &other.mHead;
if (!empty())
{
node = mHead.next();
mHead.unlink();
mHead.reset();
}
node_base* other_node = &mHead;
if (!other.empty())
{
other_node = other.mHead.next();
other.mHead.unlink();
other.mHead.reset();
}
mHead.link(other_node);
other.mHead.link(node);
}
protected:
node_base mHead;
};
//////////////////////////////////////////////////////////////////////////
// TODO: Replace with AZStd::intrusive_list
template<class T>
class intrusive_list
: public intrusive_list_base
{
intrusive_list(const intrusive_list& rhs);
intrusive_list& operator=(const intrusive_list& rhs);
public:
class node
: public node_base
{
public:
T* next() const {return static_cast<T*>(node_base::next()); }
T* prev() const {return static_cast<T*>(node_base::prev()); }
const T& data() const {return *static_cast<const T*>(this); }
T& data() {return *static_cast<T*>(this); }
};
class const_iterator;
class iterator
{
using reference = T&;
using pointer = T*;
friend class const_iterator;
T* mPtr;
public:
iterator()
: mPtr(0) {}
explicit iterator(T* ptr)
: mPtr(ptr) {}
reference operator*() const {return mPtr->data(); }
pointer operator->() const {return &mPtr->data(); }
operator pointer() const {
return &mPtr->data();
}
iterator& operator++()
{
mPtr = mPtr->next();
return *this;
}
iterator& operator--()
{
mPtr = mPtr->prev();
return *this;
}
bool operator==(const iterator& rhs) const {return mPtr == rhs.mPtr; }
bool operator!=(const iterator& rhs) const {return mPtr != rhs.mPtr; }
T* ptr() const {return mPtr; }
};
class const_iterator
{
using reference = const T &;
using pointer = const T *;
const T* mPtr;
public:
const_iterator()
: mPtr(0) {}
explicit const_iterator(const T* ptr)
: mPtr(ptr) {}
const_iterator(const iterator& it)
: mPtr(it.mPtr) {}
reference operator*() const {return mPtr->data(); }
pointer operator->() const {return &mPtr->data(); }
operator pointer() const {
return &mPtr->data();
}
const_iterator& operator++()
{
mPtr = mPtr->next();
return *this;
}
const_iterator& operator--()
{
mPtr = mPtr->prev();
return *this;
}
bool operator==(const const_iterator& rhs) const {return mPtr == rhs.mPtr; }
bool operator!=(const const_iterator& rhs) const {return mPtr != rhs.mPtr; }
const T* ptr() const {return mPtr; }
};
intrusive_list()
: intrusive_list_base() {}
~intrusive_list() {clear(); }
const_iterator begin() const {return const_iterator((const T*)mHead.next()); }
iterator begin() {return iterator((T*)mHead.next()); }
const_iterator end() const {return const_iterator((const T*)&mHead); }
iterator end() {return iterator((T*)&mHead); }
const T& front() const
{
HPPA_ASSERT(!empty());
return *begin();
}
T& front()
{
HPPA_ASSERT(!empty());
return *begin();
}
const T& back() const
{
HPPA_ASSERT(!empty());
return *(--end());
}
T& back()
{
HPPA_ASSERT(!empty());
return *(--end());
}
void push_front(T* v) {insert(this->begin(), v); }
void pop_front() {erase(this->begin()); }
void push_back(T* v) {insert(this->end(), v); }
void pop_back() {erase(--(this->end())); }
iterator insert(iterator where, T* node)
{
T* newLink = node;
newLink->link(where.ptr());
return iterator(newLink);
}
iterator erase(iterator where)
{
T* node = where.ptr();
++where;
node->unlink();
return where;
}
void erase(T* node)
{
node->unlink();
}
void clear()
{
while (!this->empty())
{
this->pop_back();
}
}
};
namespace HphaInternal
{
//! Rounds up a value to next power of 2.
//! For example to round 8388609((2^23) + 1) up to 16777216(2^24) the following occurs
//! Subtract one from the value in case it is already
//! equal to a power of 2
//! 8388609 - 1 = 8388608
//! Propagate the highest one bit in the value to all the lower bits
//! 8388608 = 0b100'0000'0000'0000'0000'0000 in binary
//!
//! 0b100'0000'0000'0000'0000'0000
//! |0b010'0000'0000'0000'0000'0000 (>> 1)
//! -------------------------------
//! 0b110'0000'0000'0000'0000'0000 (Now there are 2 consecutive 1-bits)
//! |0b001'1000'0000'0000'0000'0000 (>> 2)
//! -------------------------------
//! 0b111'1000'0000'0000'0000'0000 (Now there are 4 consecutive 1-bits)
//! |0b000'0111'1000'0000'0000'0000 (>> 4)
//! -------------------------------
//! 0b111'1111'1000'0000'0000'0000 (Now there are 8 consecutive 1-bits)
//! |0b000'0000'0111'1111'1000'0000 (>> 8)
//! -------------------------------
//! 0b111'1111'1111'1111'1000'0000 (Now there are 16 consecutive 1-bits)
//! |0b000'0000'0000'0000'0111'1111 (>> 16)
//! -------------------------------
//! 0b111'1111'1111'1111'1111'1111 (Now there are 23 consecutive 1-bits)
//! |0b000'0000'0000'0000'0000'0000 (>> 32)
//! -------------------------------
//! 0b111'1111'1111'1111'1111'1111
//! Finally since all the one bits are set in the value, adding one pushes it
//! to next power of 2
//! 0b1000'0000'0000'0000'0000'0000 = 16777216
static constexpr size_t AlignUpToPowerOfTwo(size_t value)
{
// If the value is <=2 it is already aligned
if (value <= 2)
{
return value;
}
// Subtract one to make any values already
// aligned to a power of 2 less than that power of 2
// so that algorithm doesn't push those values upwards
--value;
value |= value >> 0b1;
value |= value >> 0b10;
value |= value >> 0b100;
value |= value >> 0b1000;
value |= value >> 0b1'0000;
value |= value >> 0b10'0000;
++value;
return value;
}
static_assert(AlignUpToPowerOfTwo(0) == 0);
static_assert(AlignUpToPowerOfTwo(1) == 1);
static_assert(AlignUpToPowerOfTwo(2) == 2);
static_assert(AlignUpToPowerOfTwo(3) == 4);
static_assert(AlignUpToPowerOfTwo(4) == 4);
static_assert(AlignUpToPowerOfTwo(5) == 8);
static_assert(AlignUpToPowerOfTwo(8) == 8);
static_assert(AlignUpToPowerOfTwo(10) == 16);
static_assert(AlignUpToPowerOfTwo(16) == 16);
static_assert(AlignUpToPowerOfTwo(24) == 32);
static_assert(AlignUpToPowerOfTwo(32) == 32);
static_assert(AlignUpToPowerOfTwo(45) == 64);
static_assert(AlignUpToPowerOfTwo(64) == 64);
static_assert(AlignUpToPowerOfTwo(112) == 128);
static_assert(AlignUpToPowerOfTwo(128) == 128);
static_assert(AlignUpToPowerOfTwo(136) == 256);
static_assert(AlignUpToPowerOfTwo(256) == 256);
}
//////////////////////////////////////////////////////////////////////////
class HpAllocator
@ -376,7 +244,7 @@ namespace AZ {
};
struct page
: public block_header_proxy /* must be first */
, public intrusive_list<page>::node
, public AZStd::list_base_hook<page>::node_type
{
page(size_t elemSize, size_t pageSize, size_t marker)
: mBucketIndex((unsigned short)bucket_spacing_function_aligned(elemSize))
@ -415,25 +283,22 @@ namespace AZ {
void dec_ref() { HPPA_ASSERT(mUseCount > 0); mUseCount--; }
bool check_marker(size_t marker) const { return mMarker == (marker ^ ((size_t)this)); }
};
using page_list = intrusive_list<page>;
class bucket
using page_list = AZStd::intrusive_list<page, AZStd::list_base_hook<page>>;
#if defined(MULTITHREADED) && defined(USE_MUTEX_PER_BUCKET)
static constexpr size_t BucketAlignment = HphaInternal::AlignUpToPowerOfTwo(sizeof(page_list) + sizeof(AZStd::mutex) + sizeof(size_t));
#else
static constexpr size_t BucketAlignment = HphaInternal::AlignUpToPowerOfTwo(sizeof(page_list) + sizeof(size_t));
#endif
AZ_PUSH_DISABLE_WARNING_MSVC(4324)
class alignas(BucketAlignment) bucket
{
page_list mPageList;
#ifdef MULTITHREADED
#if defined (USE_MUTEX_PER_BUCKET)
#if defined(MULTITHREADED) && defined(USE_MUTEX_PER_BUCKET)
mutable AZStd::mutex mLock;
#endif
#endif
size_t mMarker;
#ifdef MULTITHREADED
#if defined (USE_MUTEX_PER_BUCKET)
unsigned char _padding[sizeof(void*) * 16 - sizeof(page_list) - sizeof(AZStd::mutex) - sizeof(size_t)];
#else
unsigned char _padding[sizeof(void*) * 16 - sizeof(page_list) - sizeof(size_t)];
#endif
#else
unsigned char _padding[sizeof(void*) * 4 - sizeof(page_list) - sizeof(size_t)];
#endif
public:
bucket();
#ifdef MULTITHREADED
@ -442,17 +307,19 @@ namespace AZ {
#endif
#endif
size_t marker() const {return mMarker; }
const page* page_list_begin() const {return mPageList.begin(); }
page* page_list_begin() {return mPageList.begin(); }
const page* page_list_end() const {return mPageList.end(); }
page* page_list_end() {return mPageList.end(); }
auto page_list_begin() const {return mPageList.begin(); }
auto page_list_begin() {return mPageList.begin(); }
auto page_list_end() const {return mPageList.end(); }
auto page_list_end() {return mPageList.end(); }
bool page_list_empty() const {return mPageList.empty(); }
void add_free_page(page* p) {mPageList.push_front(p); }
void add_free_page(page* p) {mPageList.push_front(*p); }
page* get_free_page();
const page* get_free_page() const;
void* alloc(page* p);
void free(page* p, void* ptr);
void unlink(page* p);
};
AZ_POP_DISABLE_WARNING_MSVC
void* bucket_system_alloc();
void bucket_system_free(void* ptr);
page* bucket_grow(size_t elemSize, size_t marker);
@ -1237,8 +1104,6 @@ namespace AZ {
// Thats why we use SimpleLcgRandom here
AZ::SimpleLcgRandom randGenerator = AZ::SimpleLcgRandom(reinterpret_cast<u64>(static_cast<void*>(this)));
mMarker = size_t(randGenerator.Getu64Random());
(void)_padding;
}
HpAllocator::page* HpAllocator::bucket::get_free_page()
@ -1278,8 +1143,8 @@ namespace AZ {
if (!next)
{
// if full, auto sort to back
p->unlink();
mPageList.push_back(p);
mPageList.erase(*p);
mPageList.push_back(*p);
}
return (void*)free;
}
@ -1295,11 +1160,16 @@ namespace AZ {
if (!free)
{
// if the page was previously full, auto sort to front
p->unlink();
mPageList.push_front(p);
mPageList.erase(*p);
mPageList.push_front(*p);
}
}
void HpAllocator::bucket::unlink(page* p)
{
mPageList.erase(*p);
}
void* HpAllocator::bucket_system_alloc()
{
void* ptr;
@ -1522,8 +1392,8 @@ namespace AZ {
AZStd::lock_guard<AZStd::mutex> lock(m_mutex);
#endif
#endif
const page* pageEnd = mBuckets[i].page_list_end();
for (const page* p = mBuckets[i].page_list_begin(); p != pageEnd; )
auto pageEnd = mBuckets[i].page_list_end();
for (auto p = mBuckets[i].page_list_begin(); p != pageEnd; )
{
// early out if we reach fully occupied page (the remaining should all be full)
if (p->mFreeList == nullptr)
@ -1537,7 +1407,7 @@ namespace AZ {
{
AZ_TracePrintf("System", "Unused Bucket %d page %p elementSize: %d available: %d elements\n", i, p, elementSize, availableMemory / elementSize);
}
p = p->next();
p = p->m_next;
}
}
return unusedMemory;
@ -1554,21 +1424,21 @@ namespace AZ {
AZStd::lock_guard<AZStd::mutex> lock(m_mutex);
#endif
#endif
page* pageEnd = mBuckets[i].page_list_end();
for (page* p = mBuckets[i].page_list_begin(); p != pageEnd; )
auto pageEnd = mBuckets[i].page_list_end();
for (auto p = mBuckets[i].page_list_begin(); p != pageEnd; )
{
// early out if we reach fully occupied page (the remaining should all be full)
if (p->mFreeList == nullptr)
{
break;
}
page* next = p->next();
page* next = p->m_next;
if (p->empty())
{
HPPA_ASSERT(p->mFreeList);
p->unlink();
mBuckets[i].unlink(AZStd::to_address(p));
p->setInvalid();
bucket_system_free(p);
bucket_system_free(AZStd::to_address(p));
}
p = next;
}
@ -2239,11 +2109,17 @@ namespace AZ {
size_t HpAllocator::tree_get_max_allocation() const
{
#ifdef MULTITHREADED
AZStd::lock_guard<AZStd::recursive_mutex> lock(mTreeMutex);
#endif
return mFreeTree.maximum()->get_block()->size();
}
size_t HpAllocator::tree_get_unused_memory(bool isPrint) const
{
#ifdef MULTITHREADED
AZStd::lock_guard<AZStd::recursive_mutex> lock(mTreeMutex);
#endif
size_t unusedMemory = 0;
for (free_node_tree::const_iterator it = mFreeTree.begin(); it != mFreeTree.end(); ++it)
{
@ -2564,7 +2440,7 @@ namespace AZ {
m_capacity = desc.m_capacity;
}
AZ_Assert(sizeof(HpAllocator) <= sizeof(m_hpAllocatorBuffer), "Increase the m_hpAllocatorBuffer, we need %d bytes but we have %d bytes!", sizeof(HpAllocator), sizeof(m_hpAllocatorBuffer));
static_assert(sizeof(HpAllocator) <= sizeof(m_hpAllocatorBuffer), "Increase the m_hpAllocatorBuffer, it needs to be at least the sizeof(HpAllocator)");
m_allocator = new (&m_hpAllocatorBuffer) HpAllocator(m_desc);
}

@ -73,18 +73,20 @@ namespace AZ
void GarbageCollect() override;
private:
// [LY-84974][sconel@][2018-08-10] SliceStrike integration up to CL 671758
// this must be at least the max size of HpAllocator (defined in the cpp) + any platform compiler padding
static const int hpAllocatorStructureSize = 16584;
// [LY][sconel@] end
// A static assert inside of HphaSchema.cpp validates that this is the case
// as of commit https://github.com/o3de/o3de/commit/92cd457c256e1ec91eeabe04b56d1d4c61f8b1af
// When MULTITHREADED and USE_MUTEX_PER_BUCKET is defined
// the largest sizeof for HpAllocator is 16640 on MacOS
// On Windows the sizeof HpAllocator is 8384
// Up this value to 18 KiB to be safe
static constexpr size_t hpAllocatorStructureSize = 18 * 1024;
Descriptor m_desc;
int m_pad; // pad the Descriptor to avoid C4355
size_type m_capacity; ///< Capacity in bytes.
HpAllocator* m_allocator;
// [LY-84974][sconel@][2018-08-10] SliceStrike integration up to CL 671758
AZStd::aligned_storage<hpAllocatorStructureSize, 16>::type m_hpAllocatorBuffer; ///< Memory buffer for HpAllocator
// [LY][sconel@] end
AZStd::aligned_storage_t<hpAllocatorStructureSize, 16> m_hpAllocatorBuffer; ///< Memory buffer for HpAllocator
bool m_ownMemoryBlock;
};
} // namespace AZ

@ -83,7 +83,7 @@
#define AZ_PUSH_DISABLE_WARNING_GCC(_gccOption)
/// Compiler specific AZ_POP_DISABLE_WARNING. This needs to be matched with the compiler specific AZ_PUSH_DISABLE_WARNINGs
#define AZ_POP_DISABLE_WARNING_CLANG
#define AZ_POP_DISABLE_WARNING_CLANG
#define AZ_POP_DISABLE_WARNING_MSVC \
__pragma(warning(pop))
#define AZ_POP_DISABLE_WARNING_GCC
@ -176,7 +176,7 @@
#define AZ_PUSH_DISABLE_WARNING_3(_1, _2, _gccOption) AZ_PUSH_DISABLE_WARNING_GCC(_gccOption)
/// Pops the warning stack. For use matched with an AZ_PUSH_DISABLE_WARNING
#define AZ_POP_DISABLE_WARNING
#define AZ_POP_DISABLE_WARNING
_Pragma("GCC diagnostic pop")
#endif // defined(AZ_COMPILER_CLANG)
@ -303,3 +303,10 @@
#if !defined(az_has_builtin_wmemmove)
#define az_has_builtin_wmemmove false
#endif
// no unique address attribute support in C++17
#if __has_cpp_attribute(no_unique_address)
#define AZ_NO_UNIQUE_ADDRESS [[no_unique_address]]
#else
#define AZ_NO_UNIQUE_ADDRESS
#endif

@ -13,6 +13,7 @@
#include <AzCore/ScriptCanvas/ScriptCanvasOnDemandNames.h>
#include <AzCore/RTTI/AzStdOnDemandPrettyName.inl>
#include <AzCore/RTTI/AzStdOnDemandReflectionLuaFunctions.inl>
#include <AzCore/std/optional.h>
#ifndef AZ_USE_CUSTOM_SCRIPT_BIND
struct lua_State;
@ -47,10 +48,6 @@ namespace AZStd
class intrusive_ptr;
template<class T>
class shared_ptr;
// Wrapper types
template <typename T>
class optional;
}
namespace AZ

@ -18,6 +18,7 @@
#include <AzCore/std/typetraits/has_member_function.h>
#include <AzCore/std/typetraits/void_t.h>
#include <AzCore/std/function/invoke.h>
#include <AzCore/std/optional.h>
#include <AzCore/Math/Uuid.h>
#include <AzCore/Math/Crc.h>
@ -89,9 +90,6 @@ namespace AZStd
template<class Signature>
class function;
template<class T>
class optional;
struct monostate;
template<class... Types>
@ -150,7 +148,7 @@ namespace AZ
template <template <typename...> class> constexpr bool false_v1 = false;
#if defined(AZ_COMPILER_MSVC)
// There is a bug with the MSVC compiler when using the 'auto' keyword here. It appears that MSVC is unable to distinguish between a template
// template argument with a type variadic pack vs a template template argument with a non-type auto variadic pack.
// template argument with a type variadic pack vs a template template argument with a non-type auto variadic pack.
template<template<AZStd::size_t...> class> constexpr bool false_v2 = false;
#else
template<template<auto...> class> constexpr bool false_v2 = false;
@ -176,7 +174,7 @@ namespace AZ
}
#if defined(AZ_COMPILER_MSVC)
// There is a bug with the MSVC compiler when using the 'auto' keyword here. It appears that MSVC is unable to distinguish between a template
// template argument with a type variadic pack vs a template template argument with a non-type auto variadic pack.
// template argument with a type variadic pack vs a template template argument with a non-type auto variadic pack.
template<template<AZStd::size_t...> class T>
#else
template<template<auto...> class T>
@ -326,7 +324,7 @@ namespace AZ
using TypeIdHolder = AZ::TypeId;
#endif
// Represents the "*" typeid that can be combined with non-pointer types T to form a unique T* typeid
// Represents the "*" typeid that can be combined with non-pointer types T to form a unique T* typeid
inline static const AZ::TypeId& PointerTypeId()
{
static TypeIdHolder s_uuid("{35C8A027-FE00-4769-AE36-6997CFFAF8AE}");
@ -977,7 +975,7 @@ namespace AZ
AZ_TYPE_INFO_INTERNAL_SPECIALIZE_CV(T, const T&, "const ", "&");
AZ_TYPE_INFO_INTERNAL_SPECIALIZE_CV(T, const T&&, "const ", "&&");
AZ_TYPE_INFO_INTERNAL_SPECIALIZE_CV(T, const T, "const ", "");
AZ_TYPE_INFO_INTERNAL_SPECIALIZED_TEMPLATE_POSTFIX_UUID(AZStd::less, "{41B40AFC-68FD-4ED9-9EC7-BA9992802E1B}", AZ_TYPE_INFO_INTERNAL_TYPENAME);
AZ_TYPE_INFO_INTERNAL_SPECIALIZED_TEMPLATE_POSTFIX_UUID(AZStd::less_equal, "{91CC0BDC-FC46-4617-A405-D914EF1C1902}", AZ_TYPE_INFO_INTERNAL_TYPENAME);
AZ_TYPE_INFO_INTERNAL_SPECIALIZED_TEMPLATE_POSTFIX_UUID(AZStd::greater, "{907F012A-7A4F-4B57-AC23-48DC08D0782E}", AZ_TYPE_INFO_INTERNAL_TYPENAME);
@ -1014,7 +1012,7 @@ namespace AZ
static constexpr const char* s_variantTypeId{ "{1E8BB1E5-410A-4367-8FAA-D43A4DE14D4B}" };
AZ_TYPE_INFO_INTERNAL_SPECIALIZED_TEMPLATE_PREFIX_UUID(AZStd::variant, "variant", s_variantTypeId, AZ_TYPE_INFO_INTERNAL_TYPENAME_VARARGS);
AZ_TYPE_INFO_INTERNAL_FUNCTION_VARIATION_SPECIALIZATION(AZStd::function, "{C9F9C644-CCC3-4F77-A792-F5B5DBCA746E}");
} // namespace AZ

@ -11,6 +11,7 @@
#include <AzCore/Outcome/Outcome.h>
#include <AzCore/Memory/OSAllocator.h>
#include <AzCore/std/containers/stack.h>
#include <AzCore/std/optional.h>
#include <AzCore/std/smart_ptr/unique_ptr.h>
#include <AzCore/std/tuple.h>
@ -47,9 +48,6 @@ namespace AZStd
class intrusive_ptr;
template<class T>
class shared_ptr;
template<class T>
class optional;
}
namespace AZ

@ -8,6 +8,7 @@
#pragma once
#include <AzCore/std/parallel/mutex.h>
#include <AzCore/std/parallel/scoped_lock.h>
namespace AZ

@ -159,6 +159,36 @@ namespace UnitTest
TeardownAllocator();
}
};
/**
* RAII wrapper around a BenchmarkEnvironmentBase to encapsulate
* the creation and destuction of the SystemAllocator
* SetUpBenchmark and TearDownBenchmark can still be used for custom
* benchmark environment setup
*/
class ScopedAllocatorBenchmarkEnvironment
: public AZ::Test::BenchmarkEnvironmentBase
{
public:
ScopedAllocatorBenchmarkEnvironment()
{
// Only create the allocator if it doesn't exist
if (!AZ::AllocatorInstance<AZ::SystemAllocator>::IsReady())
{
AZ::AllocatorInstance<AZ::SystemAllocator>::Create();
m_ownsAllocator = true;
}
}
~ScopedAllocatorBenchmarkEnvironment() override
{
if (m_ownsAllocator)
{
AZ::AllocatorInstance<AZ::SystemAllocator>::Destroy();
}
}
private:
bool m_ownsAllocator{};
};
#endif
class DLLTestVirtualClass

@ -20,6 +20,10 @@ set(FILES
base.h
config.h
concepts/concepts.h
concepts/concepts_assignable.h
concepts/concepts_constructible.h
concepts/concepts_copyable.h
concepts/concepts_movable.h
createdestroy.h
docs.h
exceptions.h
@ -34,8 +38,24 @@ set(FILES
numeric.h
math.h
optional.h
ranges/all_view.h
ranges/elements_view.h
ranges/empty_view.h
ranges/iter_move.h
ranges/iter_swap.h
ranges/join_view.h
ranges/owning_view.h
ranges/ranges.h
ranges/ranges_adaptor.h
ranges/ranges_algorithm.h
ranges/ranges_functional.h
ranges/ref_view.h
ranges/single_view.h
ranges/subrange.h
ranges/split_view.h
ranges/swap.h
ranges/zip_view.h
ranges/zip_view.inl
ratio.h
reference_wrapper.h
sort.h

File diff suppressed because it is too large Load Diff

@ -0,0 +1,34 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/std/typetraits/common_reference.h>
#include <AzCore/std/typetraits/conjunction.h>
#include <AzCore/std/typetraits/integral_constant.h>
#include <AzCore/std/typetraits/is_same.h>
#include <AzCore/std/typetraits/remove_cvref.h>
#include <AzCore/std/utility/declval.h>
namespace AZStd::Internal
{
template<class LHS, class RHS, class = void>
constexpr bool assignable_from_impl = false;
template<class LHS, class RHS>
constexpr bool assignable_from_impl<LHS, RHS, enable_if_t<conjunction_v<
is_lvalue_reference<LHS>,
bool_constant<common_reference_with<const remove_reference_t<LHS>&, const remove_reference_t<RHS>&>>,
bool_constant<same_as<decltype(declval<LHS>() = declval<RHS>()), LHS>> >>> = true;
}
namespace AZStd
{
template<class LHS, class RHS>
/*concept*/ constexpr bool assignable_from = Internal::assignable_from_impl<LHS, RHS>;
}

@ -0,0 +1,26 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/std/typetraits/conjunction.h>
#include <AzCore/std/typetraits/integral_constant.h>
#include <AzCore/std/typetraits/is_constructible.h>
#include <AzCore/std/typetraits/is_convertible.h>
#include <AzCore/std/typetraits/is_destructible.h>
namespace AZStd
{
template<class T, class... Args>
/*concept*/ constexpr bool constructible_from = conjunction_v<bool_constant<destructible<T>>,
is_constructible<T, Args...> >;
template<class T>
/*concept*/ constexpr bool move_constructible = conjunction_v<bool_constant<constructible_from<T, T>>,
bool_constant<convertible_to<T, T>>>;
}

@ -0,0 +1,60 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/std/concepts/concepts_assignable.h>
#include <AzCore/std/concepts/concepts_constructible.h>
#include <AzCore/std/concepts/concepts_movable.h>
#include <AzCore/std/typetraits/integral_constant.h>
#include <AzCore/std/typetraits/is_convertible.h>
#include <AzCore/std/typetraits/conjunction.h>
namespace AZStd::Internal
{
template <class T, class = void>
constexpr bool copy_constructible_impl = false;
template <class T>
constexpr bool copy_constructible_impl<T, enable_if_t<conjunction_v<
bool_constant<move_constructible<T>>,
bool_constant<constructible_from<T, T&>>,
bool_constant<convertible_to<T&, T>>,
bool_constant<constructible_from<T, const T&>>,
bool_constant<convertible_to<const T&, T>>,
bool_constant<constructible_from<T, const T>>,
bool_constant<convertible_to<const T, T>>
>>> = true;
}
namespace AZStd
{
// copy constructible
template<class T>
/*concept*/ constexpr bool copy_constructible = Internal::copy_constructible_impl<T>;
}
namespace AZStd::Internal
{
template <class T, class = void>
constexpr bool copyable_impl = false;
template <class T>
constexpr bool copyable_impl<T, enable_if_t<conjunction_v<
bool_constant<copy_constructible<T>>,
bool_constant<movable<T>>,
bool_constant<assignable_from<T&, T&>>,
bool_constant<assignable_from<T&, const T&>>,
bool_constant<assignable_from<T&, const T>>
>>> = true;
}
namespace AZStd
{
// copyable
template<class T>
/*concept*/ constexpr bool copyable = Internal::copyable_impl<T>;
}

@ -0,0 +1,35 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/std/concepts/concepts_assignable.h>
#include <AzCore/std/concepts/concepts_constructible.h>
#include <AzCore/std/typetraits/integral_constant.h>
#include <AzCore/std/ranges/swap.h>
#include <AzCore/std/typetraits/conjunction.h>
#include <AzCore/std/typetraits/is_object.h>
namespace AZStd::Internal
{
template <class T, class = void>
constexpr bool movable_impl = false;
template <class T>
constexpr bool movable_impl<T, enable_if_t<conjunction_v<
is_object<T>,
bool_constant<move_constructible<T>>,
bool_constant<assignable_from<T&, T>>,
bool_constant<swappable<T>>
>>> = true;
}
namespace AZStd
{
// movable
template <class T>
/*concept*/ constexpr bool movable = Internal::movable_impl<T>;
}

@ -42,20 +42,13 @@ namespace AZStd
template<class U, class Hook, class Compare>
friend class intrusive_multiset;
#ifdef AZ_DEBUG_BUILD
intrusive_multiset_node()
{
m_children[0] = nullptr;
m_children[1] = nullptr;
m_neighbours[0] = nullptr;
m_neighbours[1] = nullptr;
m_parentColorSide = nullptr;
}
intrusive_multiset_node() = default;
~intrusive_multiset_node()
{
#if defined(AZ_DEBUG_BUILD)
AZSTD_CONTAINER_ASSERT(m_children[0] == nullptr && m_children[1] == nullptr && m_parentColorSide == nullptr, "AZStd::intrusive_multiset_node - intrusive list node is being destroyed while still in a container!");
}
#endif
}
// We use the lower 2 bits of the parent pointer to store
enum Bits
{
@ -95,9 +88,9 @@ namespace AZStd
AZ_FORCE_INLINE T* next() const { return m_neighbours[AZSTD_RBTREE_RIGHT]; }
protected:
T* m_children[2];
T* m_neighbours[2];
T* m_parentColorSide;
T* m_children[2]{};
T* m_neighbours[2]{};
T* m_parentColorSide{};
} AZ_MAY_ALIAS; // we access the object in such way that we potentially can break strict aliasing rules
/**
@ -659,12 +652,10 @@ namespace AZStd
--m_numElements;
#ifdef AZ_DEBUG_BUILD
nodeHook->m_children[0] = nodeHook->m_children[1] = nullptr;
nodeHook->m_parentColorSide = nullptr;
#ifdef DEBUG_INTRUSIVE_MULTISET
#if defined(AZ_DEBUG_BUILD) && defined(DEBUG_INTRUSIVE_MULTISET)
validate();
#endif
#endif
}
@ -955,8 +946,11 @@ namespace AZStd
hookNode->setParentSide(side);
}
//! pre-condition
//! @param node must be non-nullptr
inline static node_ptr_type MinOrMax(const_node_ptr_type node, SideType side)
{
AZSTD_CONTAINER_ASSERT(node != nullptr, "MinOrMax can only be called with a non-nullptr node")
const_node_ptr_type cur = node;
const_node_ptr_type minMax = cur;
while (!iterator_impl::isNil(cur))

@ -5,8 +5,7 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#ifndef AZSTD_ORDERED_MAP_H
#define AZSTD_ORDERED_MAP_H 1
#pragma once
#include <AzCore/std/containers/rbtree.h>
#include <AzCore/std/containers/node_handle.h>
@ -392,6 +391,26 @@ namespace AZStd
return originalSize - container.size();
}
// deduction guides
template<class InputIterator, class Compare = less<iter_key_type<InputIterator>>,
class Allocator = allocator>
map(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator())
->map<iter_key_type<InputIterator>, iter_mapped_type<InputIterator>, Compare, Allocator>;
template<class Key, class T, class Compare = less<Key>,
class Allocator = allocator>
map(initializer_list<pair<Key, T>>, Compare = Compare(), Allocator = Allocator())
->map<Key, T, Compare, Allocator>;
template<class InputIterator, class Allocator>
map(InputIterator, InputIterator, Allocator)
->map<iter_key_type<InputIterator>, iter_mapped_type<InputIterator>,
less<iter_key_type<InputIterator>>, Allocator>;
template<class Key, class T, class Allocator>
map(initializer_list<pair<Key, T>>, Allocator)->map<Key, T, less<Key>, Allocator>;
/**
* Ordered multimap container is complaint with \ref C++0x (23.4.2)
* This is an associative container, key can be equivalent (multiple copies of the same key value).
@ -684,7 +703,26 @@ namespace AZStd
return originalSize - container.size();
}
}
#endif // AZSTD_ORDERED_MAP_H
#pragma once
// deduction guides
template<class InputIterator, class Compare = less<iter_key_type<InputIterator>>,
class Allocator = allocator>
multimap(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator())
->multimap<iter_key_type<InputIterator>, iter_mapped_type<InputIterator>,
Compare, Allocator>;
template<class Key, class T, class Compare = less<Key>,
class Allocator = allocator>
multimap(initializer_list<pair<Key, T>>, Compare = Compare(), Allocator = Allocator())
->multimap<Key, T, Compare, Allocator>;
template<class InputIterator, class Allocator>
multimap(InputIterator, InputIterator, Allocator)
->multimap<iter_key_type<InputIterator>, iter_mapped_type<InputIterator>,
less<iter_key_type<InputIterator>>, Allocator>;
template<class Key, class T, class Allocator>
multimap(initializer_list<pair<Key, T>>, Allocator)
->multimap<Key, T, less<Key>, Allocator>;
}

@ -7,8 +7,10 @@
*/
#pragma once
#include <AzCore/std/optional.h>
#include <AzCore/std/allocator_traits.h>
#include <AzCore/std/iterator.h>
#include <AzCore/std/optional.h>
#include <AzCore/std/utils.h>
namespace AZStd
{
@ -193,4 +195,23 @@ namespace AZStd
template <typename NodeTraits>
using map_node_handle = node_handle<NodeTraits, map_node_base>;
}
inline namespace AssociativeInternal
{
// deduction guide helpers
template<class InputIterator>
using iter_value_type = typename iterator_traits<InputIterator>::value_type::second_type;
template<class InputIterator>
using iter_key_type = remove_const_t<typename iterator_traits<InputIterator>::value_type::first_type>;
template<class InputIterator>
using iter_mapped_type = typename iterator_traits<InputIterator>::value_type::second_type;
template<class InputIterator>
using iter_to_alloc_type = pair<
add_const_t<typename iterator_traits<InputIterator>::value_type::first_type>,
typename iterator_traits<InputIterator>::value_type::second_type
>;
}
}

@ -5,8 +5,7 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#ifndef AZSTD_ORDERED_SET_H
#define AZSTD_ORDERED_SET_H 1
#pragma once
#include <AzCore/std/containers/node_handle.h>
#include <AzCore/std/containers/rbtree.h>
@ -300,6 +299,26 @@ namespace AZStd
return originalSize - container.size();
}
// deduction guides
template<class InputIterator,
class Compare = less<iter_value_type<InputIterator>>,
class Allocator = allocator>
set(InputIterator, InputIterator,
Compare = Compare(), Allocator = Allocator())
->set<iter_value_type<InputIterator>, Compare, Allocator>;
template<class Key, class Compare = less<Key>, class Allocator = allocator>
set(initializer_list<Key>, Compare = Compare(), Allocator = Allocator())
->set<Key, Compare, Allocator>;
template<class InputIterator, class Allocator>
set(InputIterator, InputIterator, Allocator)
->set<iter_value_type<InputIterator>,
less<iter_value_type<InputIterator>>, Allocator>;
template<class Key, class Allocator>
set(initializer_list<Key>, Allocator)->set<Key, less<Key>, Allocator>;
/**
* Ordered multiset container is complaint with \ref C++0x (23.4.4)
* This is an associative container, key can be equivalent (multiple copies of the same key value).
@ -573,7 +592,24 @@ namespace AZStd
return originalSize - container.size();
}
}
#endif // AZSTD_ORDERED_SET_H
#pragma once
// deduction guides
template<class InputIterator,
class Compare = less<iter_value_type<InputIterator>>,
class Allocator = allocator>
multiset(InputIterator, InputIterator,
Compare = Compare(), Allocator = Allocator())
->multiset<iter_value_type<InputIterator>, Compare, Allocator>;
template<class Key, class Compare = less<Key>, class Allocator = allocator>
multiset(initializer_list<Key>, Compare = Compare(), Allocator = Allocator())
->multiset<Key, Compare, Allocator>;
template<class InputIterator, class Allocator>
multiset(InputIterator, InputIterator, Allocator)
->multiset<iter_value_type<InputIterator>,
less<iter_value_type<InputIterator>>, Allocator>;
template<class Key, class Allocator>
multiset(initializer_list<Key>, Allocator)->multiset<Key, less<Key>, Allocator>;
}

@ -5,8 +5,7 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#ifndef AZSTD_UNORDERED_MAP_H
#define AZSTD_UNORDERED_MAP_H 1
#pragma once
#include <AzCore/std/containers/node_handle.h>
#include <AzCore/std/hash_table.h>
@ -344,6 +343,66 @@ namespace AZStd
return originalSize - container.size();
}
// deduction guides
template<class InputIterator,
class Hash = hash<iter_key_type<InputIterator>>,
class Pred = equal_to<iter_key_type<InputIterator>>,
class Allocator = allocator>
unordered_map(InputIterator, InputIterator,
typename Internal::UnorderedMapTableTraits<iter_key_type<InputIterator>,
iter_mapped_type<InputIterator>, Hash, Pred, Allocator, false>::size_type = {},
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
->unordered_map<iter_key_type<InputIterator>, iter_mapped_type<InputIterator>, Hash, Pred,
Allocator>;
template<class Key, class T, class Hash = hash<Key>,
class Pred = equal_to<Key>, class Allocator = allocator>
unordered_map(initializer_list<pair<Key, T>>,
typename Internal::UnorderedMapTableTraits<Key, T, Hash, Pred, Allocator, false>::size_type = {},
Hash = Hash(),
Pred = Pred(), Allocator = Allocator())
->unordered_map<Key, T, Hash, Pred, Allocator>;
template<class InputIterator, class Allocator>
unordered_map(InputIterator, InputIterator,
typename Internal::UnorderedMapTableTraits<iter_key_type<InputIterator>, iter_mapped_type<InputIterator>,
hash<iter_key_type<InputIterator>>, equal_to<iter_key_type<InputIterator>>, Allocator, false>::size_type,
Allocator)
->unordered_map<iter_key_type<InputIterator>, iter_mapped_type<InputIterator>,
hash<iter_key_type<InputIterator>>,
equal_to<iter_key_type<InputIterator>>, Allocator>;
template<class InputIterator, class Allocator>
unordered_map(InputIterator, InputIterator, Allocator)
->unordered_map<iter_key_type<InputIterator>, iter_mapped_type<InputIterator>,
hash<iter_key_type<InputIterator>>,
equal_to<iter_key_type<InputIterator>>, Allocator>;
template<class InputIterator, class Hash, class Allocator>
unordered_map(InputIterator, InputIterator,
typename Internal::UnorderedMapTableTraits<iter_key_type<InputIterator>, iter_mapped_type<InputIterator>,
Hash, equal_to<iter_key_type<InputIterator>>, Allocator, false>::size_type,
Hash, Allocator)
->unordered_map<iter_key_type<InputIterator>, iter_mapped_type<InputIterator>, Hash,
equal_to<iter_key_type<InputIterator>>, Allocator>;
template<class Key, class T, class Allocator>
unordered_map(initializer_list<pair<Key, T>>, typename Internal::UnorderedMapTableTraits<Key, T,
hash<Key>, equal_to<Key>, Allocator, false>::size_type,
Allocator)
->unordered_map<Key, T, hash<Key>, equal_to<Key>, Allocator>;
template<class Key, class T, class Allocator>
unordered_map(initializer_list<pair<Key, T>>, Allocator)
->unordered_map<Key, T, hash<Key>, equal_to<Key>, Allocator>;
template<class Key, class T, class Hash, class Allocator>
unordered_map(initializer_list<pair<Key, T>>, typename Internal::UnorderedMapTableTraits<Key, T,
Hash, equal_to<Key>, Allocator, true>::size_type,
Hash, Allocator)
->unordered_map<Key, T, Hash, equal_to<Key>, Allocator>;
/**
* Unordered multi map container is complaint with \ref CTR1 (6.2.4.6)
* The only difference from the unordered_map is that we allow multiple entries with
@ -560,7 +619,63 @@ namespace AZStd
return originalSize - container.size();
}
// deduction guides
template<class InputIterator,
class Hash = hash<iter_key_type<InputIterator>>,
class Pred = equal_to<iter_key_type<InputIterator>>,
class Allocator = allocator>
unordered_multimap(InputIterator, InputIterator,
typename Internal::UnorderedMapTableTraits<iter_key_type<InputIterator>,
iter_mapped_type<InputIterator>, Hash, Pred, Allocator, true>::size_type = {},
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
->unordered_multimap<iter_key_type<InputIterator>, iter_mapped_type<InputIterator>,
Hash, Pred, Allocator>;
template<class Key, class T, class Hash = hash<Key>,
class Pred = equal_to<Key>, class Allocator = allocator>
unordered_multimap(initializer_list<pair<Key, T>>,
typename Internal::UnorderedMapTableTraits<Key, T, Hash, Pred, Allocator, true>::size_type = {},
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
->unordered_multimap<Key, T, Hash, Pred, Allocator>;
template<class InputIterator, class Allocator>
unordered_multimap(InputIterator, InputIterator,
typename Internal::UnorderedMapTableTraits<iter_key_type<InputIterator>, iter_mapped_type<InputIterator>,
hash<iter_key_type<InputIterator>>, equal_to<iter_key_type<InputIterator>>, Allocator, true>::size_type,
Allocator)
->unordered_multimap<iter_key_type<InputIterator>, iter_mapped_type<InputIterator>,
hash<iter_key_type<InputIterator>>,
equal_to<iter_key_type<InputIterator>>, Allocator>;
template<class InputIterator, class Allocator>
unordered_multimap(InputIterator, InputIterator, Allocator)
->unordered_multimap<iter_key_type<InputIterator>, iter_mapped_type<InputIterator>,
hash<iter_key_type<InputIterator>>,
equal_to<iter_key_type<InputIterator>>, Allocator>;
template<class InputIterator, class Hash, class Allocator>
unordered_multimap(InputIterator, InputIterator,
typename Internal::UnorderedMapTableTraits<iter_key_type<InputIterator>, iter_mapped_type<InputIterator>,
Hash, equal_to<iter_key_type<InputIterator>>, Allocator, true>::size_type,
Hash, Allocator)
->unordered_multimap<iter_key_type<InputIterator>, iter_mapped_type<InputIterator>, Hash,
equal_to<iter_key_type<InputIterator>>, Allocator>;
template<class Key, class T, class Allocator>
unordered_multimap(initializer_list<pair<Key, T>>, typename Internal::UnorderedMapTableTraits<Key, T,
hash<Key>, equal_to<Key>, Allocator, true>::size_type,
Allocator)
->unordered_multimap<Key, T, hash<Key>, equal_to<Key>, Allocator>;
template<class Key, class T, class Allocator>
unordered_multimap(initializer_list<pair<Key, T>>, Allocator)
->unordered_multimap<Key, T, hash<Key>, equal_to<Key>, Allocator>;
template<class Key, class T, class Hash, class Allocator>
unordered_multimap(initializer_list<pair<Key, T>>, typename Internal::UnorderedMapTableTraits<Key, T,
Hash, equal_to<Key>, Allocator, true>::size_type,
Hash, Allocator)
->unordered_multimap<Key, T, Hash, equal_to<Key>, Allocator>;
}
#endif // AZSTD_UNORDERED_MAP_H
#pragma once

@ -5,8 +5,7 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#ifndef AZSTD_UNORDERED_SET_H
#define AZSTD_UNORDERED_SET_H 1
#pragma once
#include <AzCore/std/containers/node_handle.h>
#include <AzCore/std/hash_table.h>
@ -253,6 +252,55 @@ namespace AZStd
return originalSize - container.size();
}
// deduction guides
template<class InputIterator,
class Hash = hash<iter_value_type<InputIterator>>,
class Pred = equal_to<iter_value_type<InputIterator>>,
class Allocator = allocator>
unordered_set(InputIterator, InputIterator,
typename Internal::UnorderedSetTableTraits<iter_value_type<InputIterator>, Hash, Pred, Allocator, false>::size_type = {},
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
->unordered_set<iter_value_type<InputIterator>,
Hash, Pred, Allocator>;
template<class T, class Hash = hash<T>,
class Pred = equal_to<T>, class Allocator = allocator>
unordered_set(initializer_list<T>,
typename Internal::UnorderedSetTableTraits<T, Hash, Pred, Allocator, false>::size_type = {},
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
->unordered_set<T, Hash, Pred, Allocator>;
template<class InputIterator, class Allocator>
unordered_set(InputIterator, InputIterator,
typename Internal::UnorderedSetTableTraits<iter_value_type<InputIterator>, hash<iter_value_type<InputIterator>>,
equal_to<iter_value_type<InputIterator>>, Allocator, false>::size_type,
Allocator)
->unordered_set<iter_value_type<InputIterator>,
hash<iter_value_type<InputIterator>>,
equal_to<iter_value_type<InputIterator>>,
Allocator>;
template<class InputIterator, class Hash, class Allocator>
unordered_set(InputIterator, InputIterator,
typename Internal::UnorderedSetTableTraits<iter_value_type<InputIterator>, Hash,
equal_to<iter_value_type<InputIterator>>, Allocator, false>::size_type,
Hash, Allocator)
->unordered_set<iter_value_type<InputIterator>, Hash,
equal_to<iter_value_type<InputIterator>>,
Allocator>;
template<class T, class Allocator>
unordered_set(initializer_list<T>,
typename Internal::UnorderedSetTableTraits<T, hash<T>, equal_to<T>, Allocator, false>::size_type,
Allocator)
->unordered_set<T, hash<T>, equal_to<T>, Allocator>;
template<class T, class Hash, class Allocator>
unordered_set(initializer_list<T>,
typename Internal::UnorderedSetTableTraits<T, Hash, equal_to<T>, Allocator, false>::size_type,
Hash, Allocator)
->unordered_set<T, Hash, equal_to<T>, Allocator>;
/**
* Unordered multi set container is complaint with \ref CTR1 (6.2.4.5)
* The only difference from the unordered_set is that we allow multiple entries with
@ -448,7 +496,52 @@ namespace AZStd
return originalSize - container.size();
}
// deduction guides
template<class InputIterator,
class Hash = hash<iter_value_type<InputIterator>>,
class Pred = equal_to<iter_value_type<InputIterator>>,
class Allocator = allocator>
unordered_multiset(InputIterator, InputIterator,
typename Internal::UnorderedSetTableTraits<iter_value_type<InputIterator>, Hash, Pred, Allocator, true>::size_type = {},
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
->unordered_multiset<iter_value_type<InputIterator>,
Hash, Pred, Allocator>;
template<class T, class Hash = hash<T>,
class Pred = equal_to<T>, class Allocator = allocator>
unordered_multiset(initializer_list<T>,
typename Internal::UnorderedSetTableTraits<T, Hash, Pred, Allocator, true>::size_type = {},
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
->unordered_multiset<T, Hash, Pred, Allocator>;
template<class InputIterator, class Allocator>
unordered_multiset(InputIterator, InputIterator,
typename Internal::UnorderedSetTableTraits<iter_value_type<InputIterator>, hash<iter_value_type<InputIterator>>,
equal_to<iter_value_type<InputIterator>>, Allocator, true>::size_type,
Allocator)
->unordered_multiset<iter_value_type<InputIterator>,
hash<iter_value_type<InputIterator>>,
equal_to<iter_value_type<InputIterator>>,
Allocator>;
template<class InputIterator, class Hash, class Allocator>
unordered_multiset(InputIterator, InputIterator,
typename Internal::UnorderedSetTableTraits<iter_value_type<InputIterator>, Hash,
equal_to<iter_value_type<InputIterator>>, Allocator, true>::size_type,
Hash, Allocator)
->unordered_multiset<iter_value_type<InputIterator>, Hash,
equal_to<iter_value_type<InputIterator>>,
Allocator>;
template<class T, class Allocator>
unordered_multiset(initializer_list<T>,
typename Internal::UnorderedSetTableTraits<T, hash<T>, equal_to<T>, Allocator, true>::size_type,
Allocator)
->unordered_multiset<T, hash<T>, equal_to<T>, Allocator>;
template<class T, class Hash, class Allocator>
unordered_multiset(initializer_list<T>,
typename Internal::UnorderedSetTableTraits<T, Hash, equal_to<T>, Allocator, true>::size_type,
Hash, Allocator)
->unordered_multiset<T, Hash, equal_to<T>, Allocator>;
}
#endif // AZSTD_UNORDERED_SET_H
#pragma once

@ -20,7 +20,7 @@ namespace AZStd
using is_transparent = void;
template <typename T>
T&& operator()(T&& t) const
constexpr T&& operator()(T&& t) const
{
return AZStd::forward<T>(t);
}

@ -19,12 +19,28 @@ namespace AZStd
template <class R, class Fn, class... ArgTypes>
struct is_invocable_r : Internal::invocable_r<R, Fn, ArgTypes...>::type {};
template <class Fn, class... ArgTypes>
struct is_nothrow_invocable
: bool_constant<noexcept(Internal::invocable<Fn, ArgTypes...>::value)>
{};
template <class R, class Fn, class... ArgTypes>
struct is_nothrow_invocable_r
: bool_constant<noexcept(Internal::invocable_r<R, Fn, ArgTypes...>::value)>
{};
template <class Fn, class... ArgTypes>
constexpr bool is_invocable_v = is_invocable<Fn, ArgTypes...>::value;
template <class R, class Fn, class ...ArgTypes>
constexpr bool is_invocable_r_v = is_invocable_r<R, Fn, ArgTypes...>::value;
template <class Fn, class... ArgTypes>
constexpr bool is_nothrow_invocable_v = is_nothrow_invocable<Fn, ArgTypes...>::value;
template <class R, class Fn, class ...ArgTypes>
constexpr bool is_nothrow_invocable_r_v = is_nothrow_invocable_r<R, Fn, ArgTypes...>::value;
template<class Fn, class... ArgTypes>
struct invoke_result
: AZStd::enable_if<Internal::invocable<Fn, ArgTypes...>::value, typename Internal::invocable<Fn, ArgTypes...>::result_type>

@ -197,9 +197,5 @@ namespace AZStd
return *reinterpret_cast<Iterator*>(&iter);
}
}
using std::size;
using std::empty;
using std::data;
} // namespace AZStd

@ -9,9 +9,14 @@
#include <AzCore/std/base.h>
#include <AzCore/std/concepts/concepts_constructible.h>
#include <AzCore/std/concepts/concepts_copyable.h>
#include <AzCore/std/concepts/concepts_movable.h>
#include <AzCore/std/ranges/iter_move.h>
#include <AzCore/std/typetraits/common_reference.h>
#include <AzCore/std/typetraits/conditional.h>
#include <AzCore/std/typetraits/conjunction.h>
#include <AzCore/std/typetraits/integral_constant.h>
#include <AzCore/std/typetraits/is_array.h>
#include <AzCore/std/typetraits/is_class.h>
#include <AzCore/std/typetraits/is_enum.h>
@ -124,21 +129,24 @@ namespace AZStd::Internal
struct incrementable_requires {};
// iterator_traits has been specialized
template <typename T>
struct incrementable_requires<T, enable_if_t<!is_primary_template_v<iterator_traits<T>>
&& is_void_v<void_t<typename iterator_traits<T>::difference_type>> >>
struct incrementable_requires<T, enable_if_t<conjunction_v<
bool_constant<!is_primary_template_v<iterator_traits<T>>>,
bool_constant<is_void_v<void_t<typename iterator_traits<T>::difference_type>>>> >>
{
using difference_type = typename iterator_traits<T>::difference_type;
};
template <typename T>
struct incrementable_requires<T, enable_if_t<is_primary_template_v<iterator_traits<T>>
&& has_difference_type_v<T>>>
struct incrementable_requires<T, enable_if_t<conjunction_v<
bool_constant<is_primary_template_v<iterator_traits<T>>>,
bool_constant<has_difference_type_v<T>>> >>
{
using difference_type = typename T::difference_type;
};
template <typename T>
struct incrementable_requires<T, enable_if_t<is_primary_template_v<iterator_traits<T>>
&& !has_difference_type_v<T>
&& integral<decltype(declval<T>() - declval<T>())> >>
struct incrementable_requires<T, enable_if_t< conjunction_v<
bool_constant<is_primary_template_v<iterator_traits<T>>>,
bool_constant<!has_difference_type_v<T>>,
bool_constant<integral<decltype(declval<T>() - declval<T>())>>> >>
{
using difference_type = make_signed_t<decltype(declval<T>() - declval<T>())>;
};
@ -164,7 +172,7 @@ namespace AZStd
using iter_reference_t = enable_if_t<Internal::dereferenceable<T>, decltype(*declval<T&>())>;
// incrementable_traits for iter_difference_t
template <typename T>
template <typename T, class = void>
struct incrementable_traits
: Internal::incrementable_requires<T> {};
template <typename T>
@ -187,14 +195,109 @@ namespace AZStd
constexpr bool indirectly_readable_impl = false;
template <class In>
constexpr bool indirectly_readable_impl<In, enable_if_t<same_as<decltype(*declval<In>()), iter_reference_t<In>>
&& same_as<decltype(AZStd::ranges::iter_move(declval<In>())), iter_rvalue_reference_t<In>>
&& common_reference_with<iter_reference_t<In>&&, iter_value_t<In>&>
&& common_reference_with<iter_reference_t<In>&&, iter_rvalue_reference_t<In>&>
&& common_reference_with<iter_rvalue_reference_t<In>&&, const iter_value_t<In>&>>> = true;
constexpr bool indirectly_readable_impl<In, enable_if_t<conjunction_v<
bool_constant<same_as<decltype(*declval<In>()), iter_reference_t<In>>>,
bool_constant<same_as<decltype(AZStd::ranges::iter_move(declval<In>())), iter_rvalue_reference_t<In>>>,
bool_constant<common_reference_with<iter_reference_t<In>&&, iter_value_t<In>&>>,
bool_constant<common_reference_with<iter_reference_t<In>&&, iter_rvalue_reference_t<In>&>>,
bool_constant<common_reference_with<iter_rvalue_reference_t<In>&&, const iter_value_t<In>&>> >>> = true;
}
template <typename T>
using iter_common_reference_t = enable_if_t<Internal::indirectly_readable_impl<T>,
common_reference_t<iter_reference_t<T>, iter_value_t<T>&>>;
}
namespace AZStd
{
// indirectly readable
template <class In>
/*concept*/ constexpr bool indirectly_readable = Internal::indirectly_readable_impl<remove_cvref_t<In>>;
}
namespace AZStd::Internal
{
// model the indirectly writable concept
template <class Out, class T, class = void>
constexpr bool indirectly_writable_impl = false;
template <class Out, class T>
constexpr bool indirectly_writable_impl<Out, T, void_t<
decltype(*declval<Out&>() = declval<T>()),
decltype(*declval<Out>() = declval<T>()),
decltype(const_cast<const iter_reference_t<Out>&&>(*declval<Out&>()) = declval<T>()),
decltype(const_cast<const iter_reference_t<Out>&&>(*declval<Out>()) = declval<T>())>
> = true;
}
namespace AZStd
{
// indirectly writable
template <class Out, class T>
/*concept*/ constexpr bool indirectly_writable = Internal::indirectly_writable_impl<Out, T>;
// indirectly movable
template<class In, class Out>
/*concept*/ constexpr bool indirectly_movable = conjunction_v<bool_constant<indirectly_readable<In>>,
bool_constant<indirectly_writable<Out, iter_rvalue_reference_t<In>>>>;
}
namespace AZStd::Internal
{
template<class In, class Out, class = void>
constexpr bool indirectly_movable_storage_impl = false;
template<class In, class Out>
constexpr bool indirectly_movable_storage_impl<In, Out, enable_if_t<conjunction_v<
bool_constant<indirectly_movable<In, Out>>,
bool_constant<indirectly_writable<Out, iter_value_t<In>>>,
bool_constant<movable<iter_value_t<In>>>,
bool_constant<constructible_from<iter_value_t<In>, iter_rvalue_reference_t<In>>>,
bool_constant<assignable_from<iter_value_t<In>&, iter_rvalue_reference_t<In>>> >>> = true;
}
namespace AZStd
{
template<class In, class Out>
/*concept*/ constexpr bool indirectly_movable_storable = Internal::indirectly_movable_storage_impl<In, Out>;
}
namespace AZStd::Internal
{
template<class In, class Out, class = void>
constexpr bool indirectly_copyable_impl = false;
template<class In, class Out>
constexpr bool indirectly_copyable_impl<In, Out, enable_if_t<conjunction_v<
bool_constant<indirectly_readable<In>>,
bool_constant<indirectly_writable<Out, iter_reference_t<In>>> >>> = true;
}
namespace AZStd
{
// indirectly copyable
template<class In, class Out>
/*concept*/ constexpr bool indirectly_copyable = Internal::indirectly_copyable_impl<In, Out>;
}
namespace AZStd::Internal
{
template<class In, class Out, class = void>
constexpr bool indirectly_copyable_storable_impl = false;
template<class In, class Out>
constexpr bool indirectly_copyable_storable_impl<In, Out, enable_if_t < conjunction_v <
bool_constant<indirectly_copyable<In, Out>>,
bool_constant<indirectly_writable<Out, iter_value_t<In>&>>,
bool_constant<indirectly_writable<Out, const iter_value_t<In>&>>,
bool_constant<indirectly_writable<Out, iter_value_t<In>&&>>,
bool_constant<indirectly_writable<Out, const iter_value_t<In>&&>>,
bool_constant<copyable<iter_value_t<In>>>,
bool_constant<constructible_from<iter_value_t<In>, iter_reference_t<In>>>,
bool_constant<assignable_from<iter_value_t<In>&, iter_reference_t<In>>>
>>> = true;
}
namespace AZStd
{
template<class In, class Out>
/*concept*/ constexpr bool indirectly_copyable_storable = Internal::indirectly_copyable_storable_impl<In, Out>;
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,67 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/std/ranges/owning_view.h>
#include <AzCore/std/ranges/ref_view.h>
namespace AZStd::ranges::views
{
namespace Internal
{
template<class T, class = void>
constexpr bool convertible_to_ref_view = false;
template<class T>
constexpr bool convertible_to_ref_view<T, void_t<decltype(ranges::ref_view(declval<T>()))>> = true;
struct all_fn
: Internal::range_adaptor_closure<all_fn>
{
template<class View>
constexpr auto operator()(View&& t) const noexcept(noexcept(static_cast<decay_t<View>>(AZStd::forward<View>(t))))
->enable_if_t<ranges::view<decay_t<View>>, decltype(static_cast<decay_t<View>>(AZStd::forward<View>(t)))>
{
return static_cast<decay_t<View>>(AZStd::forward<View>(t));
}
template<class View>
constexpr auto operator()(View&& t) const noexcept(noexcept(ranges::ref_view(AZStd::forward<View>(t))))
->enable_if_t<conjunction_v<
bool_constant<!ranges::view<decay_t<View>>>,
bool_constant<convertible_to_ref_view<View>>>, decltype(ranges::ref_view(AZStd::forward<View>(t)))>
{
return ranges::ref_view(AZStd::forward<View>(t));
}
template<class View>
constexpr auto operator()(View&& t) const noexcept(noexcept(ranges::owning_view(AZStd::forward<View>(t))))
->enable_if_t<conjunction_v<
bool_constant<!ranges::view<decay_t<View>>>,
bool_constant<!convertible_to_ref_view<View>>>, decltype(ranges::owning_view(AZStd::forward<View>(t)))>
{
return ranges::owning_view(AZStd::forward<View>(t));
}
};
}
inline namespace customization_point_object
{
constexpr Internal::all_fn all{};
}
namespace Internal
{
template <class R, class = void>
struct all_t {};
template <class R>
struct all_t<R, enable_if_t<ranges::viewable_range<R>>>
{
using type = decltype(views::all(declval<R>()));
};
}
template<class R>
using all_t = typename Internal::all_t<R>::type;
}

@ -0,0 +1,475 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/std/ranges/all_view.h>
#include <AzCore/std/ranges/ranges_adaptor.h>
namespace AZStd::ranges
{
namespace Internal
{
template<class T, size_t N, class = void>
/*concept*/ constexpr bool has_tuple_element = false;
template<class T, size_t N>
/*concept*/ constexpr bool has_tuple_element<T, N, enable_if_t<conjunction_v<
sfinae_trigger<typename tuple_size<T>::type>,
bool_constant<(N < tuple_size_v<T>)>,
sfinae_trigger<tuple_element_t<N, T>>,
bool_constant<convertible_to<decltype(AZStd::get<N>(declval<T>())), const tuple_element_t<N, T>&>> >
>> = true;
template<class T, size_t N, class = void>
/*concept*/ constexpr bool returnable_element = false;
template<class T, size_t N>
/*concept*/ constexpr bool returnable_element<T, N, enable_if_t<
is_reference_v<T>> > = true;
template<class T, size_t N>
/*concept*/ constexpr bool returnable_element<T, N, enable_if_t<
move_constructible<tuple_element_t<N, T>>> > = true;
}
template<class View, size_t N, class = enable_if_t<conjunction_v<
bool_constant<input_range<View>>,
bool_constant<view<View>>,
bool_constant<Internal::has_tuple_element<range_value_t<View>, N>>,
bool_constant<Internal::has_tuple_element<remove_reference_t<range_reference_t<View>>, N>>,
bool_constant<Internal::returnable_element<range_reference_t<View>, N>> >
>>
class elements_view;
// Alias for elements_view which is useful for extracting keys from associative containers
template<class View>
using keys_view = elements_view<View, 0>;
// Alias for elements_view which is useful for extracting values from associative containers
template<class View>
using values_view = elements_view<View, 1>;
template<class T, size_t N>
inline constexpr bool enable_borrowed_range<elements_view<T, N>> = enable_borrowed_range<T>;
// views::elements customization point
namespace views
{
namespace Internal
{
template<size_t N>
struct elements_fn
: Internal::range_adaptor_closure<elements_fn<N>>
{
template <class View, class = enable_if_t<conjunction_v<
bool_constant<viewable_range<View>>
>>>
constexpr auto operator()(View&& view) const
{
return elements_view<views::all_t<View>, N>(AZStd::forward<View>(view));
}
};
}
inline namespace customization_point_object
{
template<size_t N>
constexpr Internal::elements_fn<N> elements{};
constexpr auto keys = elements<0>;
constexpr auto values = elements<1>;
}
}
template<class View, size_t N, class>
class elements_view
: public view_interface<elements_view<View, N>>
{
template<bool>
struct iterator;
template<bool>
struct sentinel;
public:
template <bool Enable = default_initializable<View>,
class = enable_if_t<Enable>>
elements_view() {}
explicit constexpr elements_view(View base)
: m_base(AZStd::move(base))
{
}
template <bool Enable = copy_constructible<View>, class = enable_if_t<Enable>>
constexpr View base() const&
{
return m_base;
}
constexpr View base()&&
{
return AZStd::move(m_base);
}
template<bool Enable = !Internal::simple_view<View>, class = enable_if_t<Enable>>
constexpr auto begin()
{
return iterator<false>{ ranges::begin(m_base) };
}
template<bool Enable = range<const View>, class = enable_if_t<Enable>>
constexpr auto begin() const
{
return iterator<true>{ ranges::begin(m_base) };
}
template<bool Enable = !Internal::simple_view<View>, class = enable_if_t<Enable>>
constexpr auto end()
{
if constexpr (!common_range<View>)
{
return sentinel<false>{ ranges::end(m_base) };
}
else
{
return iterator<false>{ ranges::end(m_base) };
}
}
template<bool Enable = range<const View>>
constexpr auto end() const
{
if constexpr (!common_range<const View>)
{
return sentinel<true>{ ranges::end(m_base) };
}
else
{
return iterator<true>{ ranges::end(m_base) };
}
}
template<bool Enable = sized_range<View>, class = enable_if_t<Enable>>
constexpr auto size()
{
return ranges::size(m_base);
}
template<bool Enable = sized_range<const View>, class = enable_if_t<Enable>>
constexpr auto size() const
{
return ranges::size(m_base);
}
private:
View m_base{};
};
template<class View, size_t N, bool Const, class = void>
struct elements_view_iterator_category {};
template<class View, size_t N, bool Const>
struct elements_view_iterator_category<View, N, Const, enable_if_t<forward_range<Internal::maybe_const<Const, View>> >>
{
private:
using Base = Internal::maybe_const<Const, View>;
using IterCategory = typename iterator_traits<iterator_t<Base>>::iterator_category;
public:
using iterator_category = conditional_t<
!is_lvalue_reference_v<decltype(AZStd::get<N>(*declval<iterator_t<Base>>()))>,
input_iterator_tag,
conditional_t<derived_from<IterCategory, random_access_iterator_tag>,
random_access_iterator_tag,
IterCategory>>;
};
template<class View, size_t N, class ViewEnable>
template<bool Const>
struct elements_view<View, N, ViewEnable>::iterator
: enable_if_t<conjunction_v<
bool_constant<input_range<View>>,
bool_constant<view<View>>,
bool_constant<Internal::has_tuple_element<range_value_t<View>, N>>,
bool_constant<Internal::has_tuple_element<remove_reference_t<range_reference_t<View>>, N>>,
bool_constant<Internal::returnable_element<range_reference_t<View>, N>> >
, elements_view_iterator_category<View, N, Const>
>
{
private:
template <bool>
friend struct sentinel;
using Base = Internal::maybe_const<Const, View>;
public:
using iterator_concept = conditional_t<random_access_range<Base>,
random_access_iterator_tag,
conditional_t<bidirectional_range<Base>,
bidirectional_iterator_tag,
conditional_t<forward_range<Base>,
forward_iterator_tag,
input_iterator_tag>>>;
using value_type = remove_cvref_t<tuple_element_t<N, range_value_t<Base>>>;
using difference_type = range_difference_t<Base>;
template<class BaseIter = iterator_t<Base>, class = enable_if_t<default_initializable<BaseIter>>>
iterator() {}
constexpr iterator(iterator_t<Base> current)
: m_current(AZStd::move(current))
{
}
template<class ViewIter = iterator_t<View>, class BaseIter = iterator_t<Base>,
class = enable_if_t<Const && convertible_to<ViewIter, BaseIter>>>
iterator(iterator<!Const> i)
: m_current(i.m_current)
{
}
constexpr iterator_t<View> base() const& noexcept
{
return m_current;
}
constexpr iterator_t<View> base() &&
{
return AZStd::move(m_current);
}
constexpr decltype(auto) operator*() const
{
return get_element(m_current);
}
constexpr iterator& operator++()
{
++m_current;
return *this;
}
constexpr decltype(auto) operator++(int)
{
if constexpr (!forward_range<Base>)
{
++m_current;
}
else
{
auto tmp = *this;
++(*this);
return tmp;
}
}
template<bool Enable = bidirectional_range<Base>, class = enable_if_t<Enable>>
constexpr iterator& operator--() const
{
--m_current;
return *this;
}
template<bool Enable = bidirectional_range<Base>, class = enable_if_t<Enable>>
constexpr iterator operator--(int) const
{
auto tmp = *this;
--(*this);
return tmp;
}
template<bool Enable = random_access_range<Base>, class = enable_if_t<Enable>>
constexpr iterator& operator+=(difference_type n)
{
m_current += n;
return *this;
}
template<bool Enable = random_access_range<Base>, class = enable_if_t<Enable>>
constexpr iterator& operator-=(difference_type n)
{
m_current -= n;
return *this;
}
template<bool Enable = random_access_range<Base>, class = enable_if_t<Enable>>
constexpr decltype(auto) operator[](difference_type n) const
{
return get_element(m_current + n);
}
// equality_comparable
template<class BaseIter = iterator_t<Base>, class = enable_if_t<equality_comparable<BaseIter>>>
friend constexpr bool operator==(const iterator& x, const iterator& y)
{
return x.m_current == y.m_current;
}
friend constexpr bool operator!=(const iterator& y, const iterator& x)
{
return !operator==(x, y);
}
// strict_weak_order
template<bool Enable = random_access_range<Base>, class = enable_if_t<Enable>>
friend constexpr bool operator<(const iterator& x, const iterator& y)
{
return x.m_current < y.m_current;
}
template<bool Enable = random_access_range<Base>, class = enable_if_t<Enable>>
friend constexpr bool operator>(const iterator& x, const iterator& y)
{
return y < x;
}
template<bool Enable = random_access_range<Base>, class = enable_if_t<Enable>>
friend constexpr bool operator<=(const iterator& x, const iterator& y)
{
return !(y < x);
}
template<bool Enable = random_access_range<Base>, class = enable_if_t<Enable>>
friend constexpr bool operator>=(const iterator& x, const iterator& y)
{
return !(x < y);
}
template<bool Enable = random_access_range<Base>, class = enable_if_t<Enable>>
friend constexpr iterator operator+(const iterator& x, difference_type n)
{
iterator iterCopy(x);
iterCopy += n;
return iterCopy;
}
template<bool Enable = random_access_range<Base>, class = enable_if_t<Enable>>
friend constexpr iterator operator+(difference_type n, const iterator& x)
{
return n + x;
}
template<bool Enable = random_access_range<Base>, class = enable_if_t<Enable>>
friend constexpr iterator operator-(const iterator& x, difference_type n)
{
iterator iterCopy(x);
iterCopy -= n;
return iterCopy;
}
template<class BaseIter = iterator_t<Base>, class = enable_if_t<sized_sentinel_for<BaseIter, BaseIter>>>
friend constexpr difference_type operator-(const iterator& x, const iterator& y)
{
return x.m_current - y.m_current;
}
private:
static constexpr decltype(auto) get_element(const iterator_t<Base>& i)
{
if constexpr (is_reference_v<range_reference_t<Base>>)
{
// Return a reference to the element of the tuple like type
return AZStd::get<N>(*i);
}
else
{
// Cast the result of calling AZStd::get on value type reference
using E = remove_cv_t<tuple_element_t<N, range_reference_t<Base>>>;
return static_cast<E>(AZStd::get<N>(*i));
}
}
//! iterator to range being viewed
iterator_t<Base> m_current{};
};
namespace ElementsViewInternal
{
struct requirements_fulfilled {};
}
template<class View, size_t N, class ViewEnable>
template<bool Const>
struct elements_view<View, N, ViewEnable>::sentinel
: enable_if_t<conjunction_v<
bool_constant<input_range<View>>,
bool_constant<view<View>>,
bool_constant<Internal::has_tuple_element<range_value_t<View>, N>>,
bool_constant<Internal::has_tuple_element<remove_reference_t<range_reference_t<View>>, N>>,
bool_constant<Internal::returnable_element<range_reference_t<View>, N>> >
, ElementsViewInternal::requirements_fulfilled>
{
private:
using Base = Internal::maybe_const<Const, View>;
public:
sentinel() = default;
explicit constexpr sentinel(sentinel_t<View> end)
: m_end(end)
{
}
template<class SentinelView = sentinel_t<View>, class SentinelBase = sentinel_t<Base>,
class = enable_if_t<Const && convertible_to<SentinelView, SentinelBase>>>
constexpr sentinel(sentinel<!Const> s)
: m_end(AZStd::move(s.m_end))
{
}
constexpr sentinel_t<View> base() const
{
return m_end;
}
// comparison operators
template<bool OtherConst, class = enable_if_t<
sentinel_for<sentinel_t<Base>, iterator_t<Internal::maybe_const<OtherConst, Base>>>
>>
friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y)
{
return iterator_accessor(x) == y.m_end;
}
template<bool OtherConst>
friend constexpr bool operator==(const sentinel& y, const iterator<OtherConst>& x)
{
return operator==(x, y);
}
template<bool OtherConst>
friend constexpr bool operator!=(const iterator<OtherConst>& x, const sentinel& y)
{
return !operator==(x, y);
}
template<bool OtherConst>
friend constexpr bool operator!=(const sentinel& y, const iterator<OtherConst>& x)
{
return !operator==(x, y);
}
// difference operator
template<bool OtherConst, class = enable_if_t<
sized_sentinel_for<sentinel_t<Base>, iterator_t<Internal::maybe_const<OtherConst, Base>>>
>>
friend constexpr range_difference_t<Internal::maybe_const<OtherConst, Base >>
operator-(const iterator<OtherConst>& x, const sentinel& y)
{
return iterator_accessor(x) - y.m_end;
}
template<bool OtherConst, class = enable_if_t<
sized_sentinel_for<sentinel_t<Base>, iterator_t<Internal::maybe_const<OtherConst, Base>>>
>>
friend constexpr range_difference_t<Internal::maybe_const<OtherConst, Base>>
operator-(const sentinel& x, const iterator<OtherConst>& y)
{
return x.m_end - iterator_accessor(y);
}
private:
// On MSVC The friend functions are can only access the sentinel struct members
// The iterator struct which is a friend of the sentinel struct is NOT a friend
// of the friend functions
// So a shim is added to provide access to the iterator m_current member
template<bool OtherConst>
static constexpr auto iterator_accessor(const iterator<OtherConst>& it)
{
return it.m_current;
}
sentinel_t<Base> m_end{};
};
}

@ -0,0 +1,37 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/std/ranges/ranges.h>
namespace AZStd::ranges
{
template<class T, class = void>
class empty_view;
template<class T>
class empty_view<T, enable_if_t<is_object_v<T>>>
: public view_interface<empty_view<T>>
{
public:
static constexpr T* begin() noexcept { return nullptr; }
static constexpr T* end() noexcept { return nullptr; }
static constexpr T* data() noexcept { return nullptr; }
static constexpr size_t size() noexcept { return 0; }
static constexpr bool empty() noexcept { return true; }
};
namespace views
{
template<class T>
constexpr empty_view<T> empty{};
}
template<class T>
inline constexpr bool enable_borrowed_range<empty_view<T>> = true;
}

@ -74,8 +74,16 @@ namespace AZStd::ranges::Internal
namespace AZStd::ranges
{
inline namespace customization_point_object
// Workaround for clang bug https://bugs.llvm.org/show_bug.cgi?id=37556
// Adding placing the inline customization_point_object namespace
// under a regular namespace and then aliasing that into the AZStd::ranges namespace
namespace workaround
{
inline constexpr auto iter_move = Internal::iter_move_fn{};
inline namespace customization_point_object
{
inline constexpr auto iter_move = Internal::iter_move_fn{};
}
}
using namespace workaround;
}

@ -0,0 +1,120 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/std/base.h>
#include <AzCore/std/iterator/iterator_primitives.h>
#include <AzCore/std/ranges/swap.h>
#include <AzCore/std/typetraits/conjunction.h>
#include <AzCore/std/typetraits/disjunction.h>
#include <AzCore/std/typetraits/extent.h>
#include <AzCore/std/typetraits/integral_constant.h>
#include <AzCore/std/typetraits/is_class.h>
#include <AzCore/std/typetraits/is_enum.h>
#include <AzCore/std/typetraits/is_void.h>
#include <AzCore/std/typetraits/remove_cvref.h>
#include <AzCore/std/typetraits/void_t.h>
#include <AzCore/std/utility/declval.h>
namespace AZStd::ranges::Internal
{
template<class I1, class I2>
void iter_swap(I1, I2) = delete;
template <class I1, class I2, class = void>
constexpr bool is_class_or_enum_with_iter_swap_adl = false;
template <class I1, class I2>
constexpr bool is_class_or_enum_with_iter_swap_adl<I1, I2, enable_if_t<conjunction_v<
disjunction<
disjunction<is_class<remove_cvref_t<I1>>, is_enum<remove_cvref_t<I1>>>,
disjunction<is_class<remove_cvref_t<I2>>, is_enum<remove_cvref_t<I2>>>>,
is_void<void_t<decltype(iter_swap(declval<I1>(), declval<I2>()))>>
>>> = true;
struct iter_swap_fn
{
template <class I1, class I2>
constexpr auto operator()(I1&& i1, I2&& i2) const
->enable_if_t<is_class_or_enum_with_iter_swap_adl<I1, I2>
>
{
iter_swap(AZStd::forward<I1>(i1), AZStd::forward<I1>(i2));
}
template <class I1, class I2>
constexpr auto operator()(I1&& i1, I2&& i2) const
->enable_if_t<conjunction_v<bool_constant<!is_class_or_enum_with_iter_swap_adl<I1, I2>>,
bool_constant<indirectly_readable<I1>>,
bool_constant<indirectly_readable<I2>>,
bool_constant<swappable_with<iter_reference_t<I1>, iter_reference_t<I2>>>
>>
{
ranges::swap(*i1, *i2);
}
template <class I1, class I2>
constexpr auto operator()(I1&& i1, I2&& i2) const
->enable_if_t<conjunction_v<bool_constant<!is_class_or_enum_with_iter_swap_adl<I1, I2>>,
bool_constant<!swappable_with<iter_reference_t<I1>, iter_reference_t<I2>>>,
bool_constant<indirectly_movable_storable<I1, I2>>,
bool_constant<indirectly_movable_storable<I2, I1>>
>>
{
*AZStd::forward<I1>(i1) = iter_exchange_move(AZStd::forward<I2>(i2), AZStd::forward<I1>(i1));
}
private:
template<class X, class Y>
static constexpr iter_value_t<X> iter_exchange_move(X&& x, Y&& y)
noexcept(noexcept(iter_value_t<X>(iter_move(x))) && noexcept(*x = iter_move(y)))
{
iter_value_t<X> old_value(iter_move(x));
*x = iter_move(y);
return old_value;
}
};
}
namespace AZStd::ranges
{
// Workaround for clang bug https://bugs.llvm.org/show_bug.cgi?id=37556
// Using a placeholder namespace to wrap the customization point object
// inline namespce and then bring that placeholder namespace into scope
namespace workaround
{
inline namespace customization_point_object
{
inline constexpr Internal::iter_swap_fn iter_swap{};
}
}
}
namespace AZStd::Internal
{
template <class I1, class I2, class = void>
constexpr bool indirectly_swappable_impl = false;
template <class I1, class I2>
constexpr bool indirectly_swappable_impl<I1, I2, enable_if_t<conjunction_v<
bool_constant<indirectly_readable<I1>>,
bool_constant<indirectly_readable<I2>>,
is_void<void_t<
decltype(AZStd::ranges::iter_swap(declval<I1>(), declval<I1>())),
decltype(AZStd::ranges::iter_swap(declval<I2>(), declval<I2>())),
decltype(AZStd::ranges::iter_swap(declval<I1>(), declval<I2>())),
decltype(AZStd::ranges::iter_swap(declval<I2>(), declval<I1>()))>>
>>> = true;
}
namespace AZStd
{
template<class I1, class I2 = I1>
/*concept*/ constexpr bool indirectly_swappable = Internal::indirectly_swappable_impl<I1, I2>;
}

@ -0,0 +1,430 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/std/ranges/all_view.h>
#include <AzCore/std/ranges/ranges_adaptor.h>
#include <AzCore/std/ranges/ranges_functional.h>
namespace AZStd::ranges
{
template<class View, class = enable_if_t<conjunction_v<
bool_constant<input_range<View>>,
bool_constant<view<View>>,
bool_constant<input_range<range_reference_t<View>>>
>>>
class join_view;
// views::join customization point
namespace views
{
namespace Internal
{
struct join_view_fn
: Internal::range_adaptor_closure<join_view_fn>
{
template <class View, class = enable_if_t<conjunction_v<
bool_constant<viewable_range<View>>
>>>
constexpr auto operator()(View&& view) const
{
return join_view(views::all(AZStd::forward<View>(view)));
}
};
}
inline namespace customization_point_object
{
constexpr Internal::join_view_fn join{};
}
}
template<class View, class>
class join_view
: public view_interface<join_view<View>>
{
template<bool>
struct iterator;
template<bool>
struct sentinel;
public:
template <bool Enable = default_initializable<View>,
class = enable_if_t<Enable>>
join_view() {}
explicit constexpr join_view(View base)
: m_base(AZStd::move(base))
{}
template <bool Enable = copy_constructible<View>, class = enable_if_t<Enable>>
constexpr View base() const&
{
return m_base;
}
constexpr View base() &&
{
return AZStd::move(m_base);
}
constexpr auto begin()
{
constexpr bool UseConst = Internal::simple_view<View> && is_reference_v<range_reference_t<View>>;
return iterator<UseConst>{ *this, ranges::begin(m_base) };
}
template<class ConstView = const View,
class = enable_if_t<input_range<ConstView> && is_reference_v<range_reference_t<ConstView>>>>
constexpr auto begin() const
{
return iterator<true>{ *this, ranges::begin(m_base) };
}
constexpr decltype(auto) end()
{
if constexpr (forward_range<View> && is_reference_v<InnerRange> &&
forward_range<InnerRange> && common_range<View> && common_range<InnerRange>)
{
return iterator<Internal::simple_view<View>>{ *this, ranges::end(m_base) };
}
else
{
return sentinel<Internal::simple_view<View>>{ *this };
}
}
template<class ConstView = const View,
class = enable_if_t<input_range<ConstView> && is_reference_v<range_reference_t<ConstView>>>>
constexpr auto end() const
{
if constexpr (forward_range<const View> && forward_range<range_reference_t<const View>> &&
common_range<const View> && common_range<range_reference_t<const View>>)
{
return iterator<true>{ *this, ranges::end(m_base) };
}
else
{
return sentinel<true>{ *this };
}
}
private:
View m_base{};
using InnerRange = range_reference_t<View>;
// When the inner range for the view is a reference it doesn't need to be stored
struct InnerRangeIsReference {};
using InnerRange_t = conditional_t<is_reference_v<InnerRange>, InnerRangeIsReference,
Internal::non_propagating_cache<remove_cv_t<InnerRange>>>;
AZ_NO_UNIQUE_ADDRESS InnerRange_t m_inner{};
};
template<class View, bool Const, class = void>
struct join_view_iterator_category {};
template<class View, bool Const>
struct join_view_iterator_category<View, Const, enable_if_t<conjunction_v<
is_reference<range_reference_t<Internal::maybe_const<Const, View>>>,
bool_constant<forward_range<Internal::maybe_const<Const, View>>>,
bool_constant<forward_range<range_reference_t<Internal::maybe_const<Const, View>>>>
>>>
{
private:
using Base = Internal::maybe_const<Const, View>;
using OuterC = typename iterator_traits<iterator_t<Base>>::iterator_category;
using InnerC = typename iterator_traits<iterator_t<range_reference_t<Base>>>::iterator_category;
public:
using iterator_category = conditional_t<conjunction_v<
bool_constant<derived_from<OuterC, bidirectional_iterator_tag>>,
bool_constant<derived_from<InnerC, bidirectional_iterator_tag>>,
bool_constant<common_range<range_reference_t<Base>>> >,
bidirectional_iterator_tag,
conditional_t<conjunction_v<
bool_constant<derived_from<OuterC, forward_iterator_tag>>,
bool_constant<derived_from<InnerC, forward_iterator_tag>> >,
forward_iterator_tag,
input_iterator_tag>>;
};
template<class R>
join_view(R&&) -> join_view<views::all_t<R>>;
template<class View, class ViewEnable>
template<bool Const>
struct join_view<View, ViewEnable>::iterator
: enable_if_t<conjunction_v<
bool_constant<input_range<View>>,
bool_constant<view<View>>,
bool_constant<input_range<range_reference_t<View>>>
>, join_view_iterator_category<View, Const>
>
{
private:
template<bool>
friend struct sentinel;
using Parent = Internal::maybe_const<Const, join_view>;
using Base = Internal::maybe_const<Const, View>;
using OuterIter = iterator_t<Base>;
using InnerIter = iterator_t<range_reference_t<Base>>;
static constexpr bool ref_is_glvalue = is_reference_v<range_reference_t<Base>>;
public:
using iterator_concept = conditional_t<ref_is_glvalue && bidirectional_range<Base>
&& common_range<Base>, bidirectional_iterator_tag,
conditional_t<ref_is_glvalue && forward_range<Base> && forward_range<range_reference_t<Base>>,
forward_iterator_tag,
input_iterator_tag>>;
using value_type = range_value_t<range_reference_t<Base>>;
using difference_type = common_type_t<range_difference_t<Base>,
range_difference_t<range_reference_t<Base>>>;
template<bool Enable = default_initializable<OuterIter> && default_initializable<InnerIter>,
class = enable_if_t<Enable>>
iterator() {}
constexpr iterator(join_view& parent, OuterIter outer)
: m_parent(addressof(parent))
, m_outer(AZStd::move(outer))
{
satisfy();
}
template<bool Enable = convertible_to<iterator_t<View>, OuterIter> &&
convertible_to<iterator_t<InnerRange>, InnerIter>,
class = enable_if_t<Enable>>
iterator(iterator<!Const> i)
: m_parent(i.m_parent)
, m_outer(i.m_outer)
, m_inner(i.m_inner)
{}
constexpr iterator_t<View> base() const
{
return m_inner;
}
constexpr decltype(auto) operator*() const
{
return *m_inner;
}
template<bool Enable = Internal::has_arrow<InnerIter> && copyable<InnerIter>,
class = enable_if_t<Enable>>
constexpr InnerIter operator->() const
{
return m_inner;
}
constexpr iterator& operator++()
{
if constexpr (ref_is_glvalue)
{
auto&& innerRange = *m_outer;
if (++m_inner == ranges::end(innerRange))
{
++m_outer;
satisfy();
}
}
else
{
auto&& innerRange = *m_parent->m_inner;
if (++m_inner == ranges::end(innerRange))
{
++m_outer;
satisfy();
}
}
return *this;
}
constexpr void operator++(int)
{
++(*this);
}
template<bool Enable = ref_is_glvalue && bidirectional_range<Base> && bidirectional_range<range_reference_t<Base>>,
class = enable_if_t<Enable && common_range<range_reference_t<Base>>>>
constexpr iterator& operator--() const
{
if (m_outer == ranges::end(m_parent->m_base))
{
m_inner = ranges::end(*--m_outer);
}
// Move inner iterator backwards to the last element of the first non-empty outer iterator
// by iterating backwards
while (m_inner == ranges::begin(*m_outer))
{
m_inner = ranges::end(*--m_outer);
--m_inner;
}
return *this;
}
template<bool Enable = ref_is_glvalue && bidirectional_range<Base> && bidirectional_range<range_reference_t<Base>>,
class = enable_if_t<Enable && common_range<range_reference_t<Base>>>>
constexpr iterator operator--(int) const
{
auto tmp = *this;
--(*this);
return tmp;
}
template<class OtherBase = Base,
class = enable_if_t<ref_is_glvalue && equality_comparable<iterator_t<OtherBase>> &&
equality_comparable<iterator_t<range_reference_t<OtherBase>>>>>
friend constexpr bool operator==(const iterator& x, const iterator& y)
{
return x.m_outer == y.m_outer && x.m_inner == y.m_inner;
}
template<class OtherBase = Base,
class = enable_if_t<ref_is_glvalue && equality_comparable<iterator_t<OtherBase>>&&
equality_comparable<iterator_t<range_reference_t<OtherBase>>>>>
friend constexpr bool operator!=(const iterator& x, const iterator& y)
{
return !operator==(x, y);
}
// customization of iter_move and iter_swap
friend constexpr decltype(auto) iter_move(
iterator& i)
noexcept(noexcept(ranges::iter_move(i.m_inner)))
{
return ranges::iter_move(i.m_inner);
}
friend constexpr void iter_swap(
iterator& x,
iterator& y)
noexcept(noexcept(ranges::iter_swap(x.m_inner, y.m_inner)))
{
return ranges::iter_swap(x.m_inner, y.m_inner);
}
private:
constexpr void satisfy()
{
// dereference the outer iterator if the inner iterato is a reference
// or make a copy of deref ference of outer iterator
auto update_inner = [this](const iterator_t<Base>& x) constexpr -> auto&&
{
if constexpr (ref_is_glvalue) // *x is a reference
{
// workaround clang 9.0.0 bug where this is unused because
// of not being used in one block of the if constexpr
(void)this;
return *x;
}
else
{
return m_parent->m_inner.emplace_deref(x);
}
};
for (; m_outer != ranges::end(m_parent->m_base); ++m_outer)
{
auto&& inner = update_inner(m_outer);
m_inner = ranges::begin(inner);
// m_inner is end then the inner range is empty
// and the next outer element is iterated over
if (m_inner != ranges::end(inner))
{
return;
}
}
if constexpr (ref_is_glvalue)
{
m_inner = InnerIter();
}
}
//! iterator to the outer view element of the view wrapped by the join view
OuterIter m_outer{};
//! iterator to the actually range element which is wrapped by the view
InnerIter m_inner{};
//! reference to parent join_view
join_view<View>* m_parent{};
};
// sentinel type for iterator
namespace JoinViewInternal
{
struct requirements_fulfilled {};
}
template<class View, class ViewEnable>
template<bool Const>
struct join_view<View, ViewEnable>::sentinel
: enable_if_t<conjunction_v<
bool_constant<input_range<View>>,
bool_constant<view<View>>,
bool_constant<input_range<range_reference_t<View>>>
>, JoinViewInternal::requirements_fulfilled>
{
private:
using Parent = Internal::maybe_const<Const, join_view>;
using Base = Internal::maybe_const<Const, View>;
public:
sentinel() = default;
explicit constexpr sentinel(Parent& parent)
: m_end(ranges::end(parent.m_base))
{}
template<bool Enable = Const,
class = enable_if_t<Enable && convertible_to<sentinel_t<View>, sentinel_t<Base>>>>
constexpr sentinel(sentinel<!Const> s)
: m_end(AZStd::move(s.m_end))
{
}
// comparison operators
template<bool OtherConst, class = enable_if_t<
sentinel_for<sentinel_t<Base>, iterator_t<Internal::maybe_const<OtherConst, Base>>>
>>
friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y)
{
return iterator_accessor(x) == y.m_end;
}
template<bool OtherConst, class = enable_if_t<
sentinel_for<sentinel_t<Base>, iterator_t<Internal::maybe_const<OtherConst, Base>>>
>>
friend constexpr bool operator==(const sentinel& y, const iterator<OtherConst>& x)
{
return operator==(x, y);
}
template<bool OtherConst, class = enable_if_t<
sentinel_for<sentinel_t<Base>, iterator_t<Internal::maybe_const<OtherConst, Base>>>
>>
friend constexpr bool operator!=(const iterator<OtherConst>& x, const sentinel& y)
{
return !operator==(x, y);
}
template<bool OtherConst, class = enable_if_t<
sentinel_for<sentinel_t<Base>, iterator_t<Internal::maybe_const<OtherConst, Base>>>
>>
friend constexpr bool operator!=(const sentinel& y, const iterator<OtherConst>& x)
{
return !operator==(x, y);
}
private:
// On MSVC The friend functions are can only access the sentinel struct members
// The iterator struct which is a friend of the sentinel struct is NOT a friend
// of the friend functions
// So a shim is added to provide access to the iterator m_current member
template<bool OtherConst>
static constexpr auto iterator_accessor(const iterator<OtherConst>& it)
{
return it.m_outer;
}
sentinel_t<Base> m_end{};
};
}

@ -0,0 +1,114 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/std/ranges/ranges_adaptor.h>
namespace AZStd::ranges
{
template<class R, class = void>
class owning_view;
template<class R>
class owning_view<R, enable_if_t<ranges::range<R> && movable<R> &&
!Internal::is_initializer_list<remove_cvref_t<R>> >>
: public ranges::view_interface<owning_view<R>>
{
public:
template<class T = R, enable_if_t<default_initializable<T>>>
constexpr owning_view() {}
constexpr owning_view(R&& t)
: m_range{ AZStd::move(t) }
{}
constexpr owning_view(owning_view&&) = default;
constexpr owning_view& operator=(owning_view&&) = default;
constexpr R& base() & noexcept
{
return m_range;
}
constexpr const R& base() const& noexcept
{
return m_range;
}
constexpr R&& base() && noexcept
{
return AZStd::move(m_range);
}
constexpr const R&& base() const&& noexcept
{
return AZStd::move(m_range);
}
constexpr iterator_t<R> begin()
{
return ranges::begin(m_range);
}
constexpr sentinel_t<R> end()
{
return ranges::end(m_range);
}
template<class Rn = R>
constexpr auto begin() const -> enable_if_t<range<const R>, decltype(ranges::begin(declval<Rn>()))>
{
return ranges::begin(m_range);
}
template<class Rn = R>
constexpr auto end() const -> enable_if_t<range<const R>, decltype(ranges::end(declval<Rn>()))>
{
return ranges::end(m_range);
}
template<class Rn = R>
constexpr auto empty() -> enable_if_t<Internal::sfinae_trigger_v<decltype(ranges::empty(declval<Rn>()))>, bool>
{
return ranges::empty(m_range);
}
template<class Rn = R>
constexpr auto empty() const -> enable_if_t<Internal::sfinae_trigger_v<decltype(ranges::empty(declval<Rn>()))>, bool>
{
return ranges::empty(m_range);
}
template<class Rn = R>
constexpr auto size() -> enable_if_t<sized_range<R>, decltype(ranges::size(declval<Rn>()))>
{
return ranges::size(m_range);
}
template<class Rn = R>
constexpr auto size() const -> enable_if_t<sized_range<const R>, decltype(ranges::size(declval<Rn>()))>
{
return ranges::size(m_range);
}
template<class Rn = R>
constexpr auto data() -> enable_if_t<contiguous_range<R>, decltype(ranges::data(declval<Rn>()))>
{
return ranges::data(m_range);
}
template<class Rn = R>
constexpr auto data() const -> enable_if_t<contiguous_range<const R>, decltype(ranges::data(declval<Rn>()))>
{
return ranges::data(m_range);
}
private:
R m_range;
};
//! deduction guides
template<class R>
owning_view(R&&) -> owning_view<R>;
template<class T>
inline constexpr bool enable_borrowed_range<owning_view<T>> = enable_borrowed_range<T>;
}

@ -36,10 +36,12 @@ namespace AZStd::ranges
{
// Variadic template which maps types to true For SFINAE
template <class... Args>
using sfinae_trigger = true_type;
template <class... Args>
constexpr bool sfinae_trigger_v = true;
template <class T>
constexpr bool is_lvalue_or_borrowable = is_lvalue_reference_v<T> || enable_borrowed_range<remove_cv_t<T>>;
constexpr bool is_lvalue_or_borrowable = disjunction_v<is_lvalue_reference<T>, bool_constant<enable_borrowed_range<remove_cv_t<T>>>>;
//! begin
template <class T, typename = void>
@ -50,8 +52,11 @@ namespace AZStd::ranges
template <class T, typename = void>
constexpr bool has_unqualified_begin = false;
template <class T>
constexpr bool has_unqualified_begin<T, void_t<decltype(begin(declval<T&>()))>>
= !has_member_begin<T> && AZStd::Internal::is_class_or_enum<T>;
constexpr bool has_unqualified_begin<T, enable_if_t<conjunction_v<
bool_constant<!has_member_begin<T>>,
bool_constant<AZStd::Internal::is_class_or_enum<T>>,
sfinae_trigger<decltype(begin(declval<T&>()))>
>>> = true;
template<class T>
void begin(T&) = delete;
@ -62,7 +67,7 @@ namespace AZStd::ranges
{
template<class T>
constexpr auto operator()(T& t) const noexcept ->
enable_if_t<is_array_v<T> && sfinae_trigger_v<remove_all_extents_t<T>>,
enable_if_t<conjunction_v<is_array<T>, sfinae_trigger<remove_all_extents_t<T>>>,
decltype(t + 0)>
{
return t + 0;
@ -70,8 +75,11 @@ namespace AZStd::ranges
template<class T>
constexpr auto operator()(T&& t) const noexcept(noexcept(AZStd::forward<T>(t).begin())) ->
enable_if_t<input_or_output_iterator<decltype(t.begin())>&& is_lvalue_or_borrowable<T>
&& !is_array_v<T>&& has_member_begin<T>,
enable_if_t<conjunction_v<
bool_constant<input_or_output_iterator<decltype(AZStd::forward<T>(t).begin())>>,
bool_constant<is_lvalue_or_borrowable<T>>,
bool_constant<!is_array_v<T>>,
bool_constant<has_member_begin<T>>>,
decltype(AZStd::forward<T>(t).begin())>
{
return AZStd::forward<T>(t).begin();
@ -79,8 +87,11 @@ namespace AZStd::ranges
template<class T>
constexpr auto operator()(T&& t) const noexcept(noexcept(begin(AZStd::forward<T>(t)))) ->
enable_if_t<input_or_output_iterator<decltype(begin(t))>&& is_lvalue_or_borrowable<T>
&& !is_array_v<T> && has_unqualified_begin<T>,
enable_if_t<conjunction_v<
bool_constant<input_or_output_iterator<decltype(begin(AZStd::forward<T>(t)))>>,
bool_constant<is_lvalue_or_borrowable<T>>,
bool_constant<!is_array_v<T>>,
bool_constant<has_unqualified_begin<T>>>,
decltype(begin(AZStd::forward<T>(t)))>
{
return begin(AZStd::forward<T>(t));
@ -109,8 +120,11 @@ namespace AZStd::ranges
template <class T, typename = void>
constexpr bool has_unqualified_end = false;
template <class T>
constexpr bool has_unqualified_end<T, void_t<decltype(end(declval<T&>()))>>
= !has_member_end<T> && AZStd::Internal::is_class_or_enum<T>;
constexpr bool has_unqualified_end<T, enable_if_t<conjunction_v<
bool_constant<!has_member_end<T>>,
bool_constant<AZStd::Internal::is_class_or_enum<T>>,
sfinae_trigger<decltype(end(declval<T&>()))>
>>> = true;
template<class T>
void end(T&) = delete;
@ -121,7 +135,7 @@ namespace AZStd::ranges
{
template<class T>
constexpr auto operator()(T& t) const noexcept ->
enable_if_t<is_array_v<T> && extent_v<T> != 0,
enable_if_t<conjunction_v<is_array<T>, bool_constant<extent_v<T> != 0>>,
decltype(t + extent_v<T>)>
{
return t + extent_v<T>;
@ -129,8 +143,11 @@ namespace AZStd::ranges
template<class T>
constexpr auto operator()(T&& t) const noexcept(noexcept(AZStd::forward<T>(t).end())) ->
enable_if_t<sentinel_for<decltype(t.end()), iterator_t<T>>&& is_lvalue_or_borrowable<T>
&& !is_array_v<T> && has_member_end<T>,
enable_if_t<conjunction_v<
bool_constant<sentinel_for<decltype(AZStd::forward<T>(t).end()), iterator_t<T>>>,
bool_constant<is_lvalue_or_borrowable<T>>,
bool_constant<!is_array_v<T>>,
bool_constant<has_member_end<T>>>,
decltype(AZStd::forward<T>(t).end())>
{
return AZStd::forward<T>(t).end();
@ -138,8 +155,11 @@ namespace AZStd::ranges
template<class T>
constexpr auto operator()(T&& t) const noexcept(noexcept(end(AZStd::forward<T>(t)))) ->
enable_if_t<sentinel_for<decltype(end(t)), iterator_t<T>>&& is_lvalue_or_borrowable<T>
&& !is_array_v<T> && has_unqualified_end<T>,
enable_if_t<conjunction_v<
bool_constant<sentinel_for<decltype(end(AZStd::forward<T>(t))), iterator_t<T>>>,
bool_constant<is_lvalue_or_borrowable<T>>,
bool_constant<!is_array_v<T>>,
bool_constant<has_unqualified_end<T>>>,
decltype(end(AZStd::forward<T>(t)))>
{
return end(AZStd::forward<T>(t));
@ -212,17 +232,22 @@ namespace AZStd::ranges
template <class T, class = void>
constexpr bool has_unqualified_rbegin = false;
template <class T>
constexpr bool has_unqualified_rbegin<T, void_t<decltype(rbegin(declval<T&>()))>>
= !has_member_rbegin<T> && AZStd::Internal::is_class_or_enum<T>;
constexpr bool has_unqualified_rbegin<T, enable_if_t<conjunction_v<
bool_constant<!has_member_rbegin<T>>,
sfinae_trigger<decltype(rbegin(declval<T&>()))>,
bool_constant<::AZStd::Internal::is_class_or_enum<T>>
>>> = true;
template <class T, class = void>
constexpr bool has_bidirectional_rbegin = false;
template <class T>
constexpr bool has_bidirectional_rbegin<T, enable_if_t<
same_as<decltype(ranges::begin(declval<T&>())), decltype(ranges::end(declval<T&>()))>
&& bidirectional_iterator<decltype(ranges::begin(declval<T&>()))>
&& bidirectional_iterator<decltype(ranges::end(declval<T&>()))>
>> = !has_member_rbegin<T> && !has_unqualified_rbegin<T>;
constexpr bool has_bidirectional_rbegin<T, enable_if_t<conjunction_v<
bool_constant<!has_member_rbegin<T>>,
bool_constant<!has_unqualified_rbegin<T>>,
bool_constant<same_as<decltype(ranges::begin(declval<T&>())), decltype(ranges::end(declval<T&>()))>>,
bool_constant<bidirectional_iterator<decltype(ranges::begin(declval<T&>()))>>,
bool_constant<bidirectional_iterator<decltype(ranges::end(declval<T&>()))>>
>>> = true;
template<class T>
@ -234,8 +259,10 @@ namespace AZStd::ranges
{
template<class T>
constexpr auto operator()(T&& t) const noexcept(noexcept(AZStd::forward<T>(t).rbegin())) ->
enable_if_t<input_or_output_iterator<decltype(t.rbegin())> && is_lvalue_or_borrowable<T>
&& has_member_rbegin<T>,
enable_if_t<conjunction_v<
bool_constant<input_or_output_iterator<decltype(AZStd::forward<T>(t).rbegin())>>,
bool_constant<is_lvalue_or_borrowable<T>>,
bool_constant<has_member_rbegin<T>>>,
decltype(AZStd::forward<T>(t).rbegin())>
{
return AZStd::forward<T>(t).rbegin();
@ -243,8 +270,10 @@ namespace AZStd::ranges
template<class T>
constexpr auto operator()(T&& t) const noexcept(noexcept(rbegin(AZStd::forward<T>(t)))) ->
enable_if_t<input_or_output_iterator<decltype(rbegin(t))> && is_lvalue_or_borrowable<T>
&& has_unqualified_rbegin<T>,
enable_if_t<conjunction_v<
bool_constant<input_or_output_iterator<decltype(rbegin(AZStd::forward<T>(t)))>>,
bool_constant<is_lvalue_or_borrowable<T>>,
bool_constant<has_unqualified_rbegin<T>>>,
decltype(rbegin(AZStd::forward<T>(t)))>
{
return rbegin(AZStd::forward<T>(t));
@ -276,17 +305,22 @@ namespace AZStd::ranges
template <class T, class = void>
constexpr bool has_unqualified_rend = false;
template <class T>
constexpr bool has_unqualified_rend<T, void_t<decltype(rend(declval<T&>()))>>
= !has_member_rend<T> && AZStd::Internal::is_class_or_enum<T>;
constexpr bool has_unqualified_rend<T, enable_if_t<conjunction_v<
bool_constant<!has_member_rend<T>>,
sfinae_trigger<decltype(rend(declval<T&>()))>,
bool_constant<::AZStd::Internal::is_class_or_enum<T>>
>>> = true;
template <class T, class = void>
constexpr bool has_bidirectional_rend = false;
template <class T>
constexpr bool has_bidirectional_rend<T, enable_if_t<
same_as<decltype(ranges::begin(declval<T&>())), decltype(ranges::end(declval<T&>()))>
&& bidirectional_iterator<decltype(ranges::begin(declval<T&>()))>
&& bidirectional_iterator<decltype(ranges::end(declval<T&>()))>
>> = !has_member_rend<T> && !has_unqualified_rend<T>;
constexpr bool has_bidirectional_rend<T, enable_if_t<conjunction_v<
bool_constant<!has_member_rend<T>>,
bool_constant<!has_unqualified_rend<T>>,
bool_constant<same_as<decltype(ranges::begin(declval<T&>())), decltype(ranges::end(declval<T&>()))>>,
bool_constant<bidirectional_iterator<decltype(ranges::begin(declval<T&>()))>>,
bool_constant<bidirectional_iterator<decltype(ranges::end(declval<T&>()))>>
>>> = true;
template<class T>
void rend(T&) = delete;
@ -297,8 +331,10 @@ namespace AZStd::ranges
{
template<class T>
constexpr auto operator()(T&& t) const noexcept(noexcept(AZStd::forward<T>(t).rend())) ->
enable_if_t<sentinel_for<decltype(t.rend()), decltype(ranges::rbegin(t))> && is_lvalue_or_borrowable<T>
&& has_member_rend<T>,
enable_if_t<conjunction_v<
bool_constant<sentinel_for<decltype(t.rend()), decltype(ranges::rbegin(AZStd::forward<T>(t)))>>,
bool_constant<is_lvalue_or_borrowable<T>>,
bool_constant<has_member_rend<T>>>,
decltype(AZStd::forward<T>(t).rend())>
{
return AZStd::forward<T>(t).rend();
@ -306,8 +342,10 @@ namespace AZStd::ranges
template<class T>
constexpr auto operator()(T&& t) const noexcept(noexcept(rend(AZStd::forward<T>(t)))) ->
enable_if_t<sentinel_for<decltype(rend(t)), decltype(ranges::rbegin(t))> && is_lvalue_or_borrowable<T>
&& has_unqualified_rend<T>,
enable_if_t<conjunction_v<
bool_constant<sentinel_for<decltype(rend(t)), decltype(ranges::rbegin(AZStd::forward<T>(t)))>>,
bool_constant<is_lvalue_or_borrowable<T>>,
bool_constant<has_unqualified_rend<T>>>,
decltype(rend(AZStd::forward<T>(t)))>
{
return rend(AZStd::forward<T>(t));
@ -389,14 +427,20 @@ namespace AZStd::ranges
template <class T, class = void>
constexpr bool has_unqualified_size = false;
template <class T>
constexpr bool has_unqualified_size<T, void_t<decltype(size(declval<T&>()))>>
= !has_member_size<T> && AZStd::Internal::is_class_or_enum<T>;
constexpr bool has_unqualified_size<T, enable_if_t<conjunction_v<
sfinae_trigger<decltype(size(declval<T&>()))>,
bool_constant<!has_member_size<T>>,
bool_constant<::AZStd::Internal::is_class_or_enum<T>>
>>> = true;
template <class T, class = void>
constexpr bool has_end_subtract_begin = false;
template <class T>
constexpr bool has_end_subtract_begin<T, void_t<decltype(ranges::end(declval<T&>()) - ranges::begin(declval<T&>()))>>
= !has_member_size<T> && !has_unqualified_size<T>;
constexpr bool has_end_subtract_begin<T, enable_if_t<conjunction_v<
sfinae_trigger<decltype(ranges::end(declval<T&>()) - ranges::begin(declval<T&>()))>,
bool_constant<!has_member_size<T>>,
bool_constant<!has_unqualified_size<T>>
>>> = true;
template<class T>
void size(T&) = delete;
@ -407,7 +451,7 @@ namespace AZStd::ranges
{
template<class T>
constexpr auto operator()(T&) const noexcept ->
enable_if_t<is_array_v<T> && extent_v<T> != 0,
enable_if_t<conjunction_v<is_array<T>, bool_constant<extent_v<T> != 0>>,
decltype(extent_v<T>)>
{
return extent_v<T>;
@ -415,8 +459,9 @@ namespace AZStd::ranges
template<class T>
constexpr auto operator()(T&& t) const noexcept(noexcept(AZStd::forward<T>(t).size())) ->
enable_if_t<!disable_sized_range<remove_cv_t<T>> && has_member_size<T>
&& AZStd::Internal::is_integer_like<decltype(AZStd::forward<T>(t).size())>,
enable_if_t<conjunction_v<bool_constant<!disable_sized_range<remove_cv_t<T>>>,
bool_constant<has_member_size<T>>,
bool_constant<::AZStd::Internal::is_integer_like<decltype(AZStd::forward<T>(t).size())>>>,
decltype(AZStd::forward<T>(t).size())>
{
return AZStd::forward<T>(t).size();
@ -424,9 +469,9 @@ namespace AZStd::ranges
template<class T>
constexpr auto operator()(T&& t) const noexcept(noexcept(size(AZStd::forward<T>(t)))) ->
enable_if_t<!disable_sized_range<remove_cv_t<T>>
&& has_unqualified_size<T>
&& AZStd::Internal::is_integer_like<decltype(size(AZStd::forward<T>(t)))>,
enable_if_t<conjunction_v<bool_constant<!disable_sized_range<remove_cv_t<T>>>,
bool_constant<has_unqualified_size<T>>,
bool_constant<::AZStd::Internal::is_integer_like<decltype(size(AZStd::forward<T>(t)))>>>,
decltype(size(AZStd::forward<T>(t)))>
{
return size(AZStd::forward<T>(t));
@ -434,10 +479,10 @@ namespace AZStd::ranges
template<class T>
constexpr auto operator()(T&& t) const noexcept(noexcept(ranges::end(AZStd::forward<T>(t)) - ranges::begin(AZStd::forward<T>(t)))) ->
enable_if_t<
has_end_subtract_begin<T>
&& sized_sentinel_for<decltype(ranges::end(AZStd::forward<T>(t))), decltype(ranges::begin(AZStd::forward<T>(t)))>
&& forward_iterator<decltype(ranges::begin(AZStd::forward<T>(t)))>,
enable_if_t<conjunction_v<
bool_constant<has_end_subtract_begin<T>>,
bool_constant<sized_sentinel_for<decltype(ranges::end(AZStd::forward<T>(t))), decltype(ranges::begin(AZStd::forward<T>(t)))>>,
bool_constant<forward_iterator<decltype(ranges::begin(AZStd::forward<T>(t)))>>>,
AZStd::make_unsigned_t<decltype(ranges::end(AZStd::forward<T>(t)) - ranges::begin(AZStd::forward<T>(t)))>>
{
using size_type = AZStd::make_unsigned_t<decltype(ranges::end(AZStd::forward<T>(t)) - ranges::begin(AZStd::forward<T>(t)))>;
@ -456,17 +501,17 @@ namespace AZStd::ranges
struct ssize_fn
{
template<class T>
constexpr auto operator()(T&& t) const noexcept(noexcept(ranges::size(t))) ->
enable_if_t<(sizeof(ptrdiff_t) > sizeof(make_signed_t<decltype(ranges::size(t))>)), ptrdiff_t>
constexpr auto operator()(T&& t) const noexcept(noexcept(ranges::size(AZStd::forward<T>(t)))) ->
enable_if_t<(sizeof(ptrdiff_t) > sizeof(make_signed_t<decltype(ranges::size(AZStd::forward<T>(t)))>)), ptrdiff_t>
{
return static_cast<ptrdiff_t>(ranges::size(t));
return static_cast<ptrdiff_t>(ranges::size(AZStd::forward<T>(t)));
}
template<class T>
constexpr auto operator()(T&& t) const noexcept(noexcept(ranges::size(t))) ->
enable_if_t<sizeof(ptrdiff_t) <= sizeof(make_signed_t<decltype(ranges::size(t))>), make_signed_t<decltype(ranges::size(t))>>
constexpr auto operator()(T&& t) const noexcept(noexcept(ranges::size(AZStd::forward<T>(t)))) ->
enable_if_t<sizeof(ptrdiff_t) <= sizeof(make_signed_t<decltype(ranges::size(AZStd::forward<T>(t)))>), make_signed_t<decltype(ranges::size(t))>>
{
using ssize_type = make_signed_t<decltype(ranges::size(t))>;
using ssize_type = make_signed_t<decltype(ranges::size(AZStd::forward<T>(t)))>;
return static_cast<ssize_type>(ranges::size(t));
}
};
@ -487,36 +532,41 @@ namespace AZStd::ranges
template <class T, class = void>
constexpr bool has_size_compare_to_0 = false;
template <class T>
constexpr bool has_size_compare_to_0<T, enable_if_t<convertible_to<decltype(ranges::size(declval<T&>()) == 0), bool> >>
= !has_member_empty<T>;
constexpr bool has_size_compare_to_0<T, enable_if_t<conjunction_v<
bool_constant<!has_member_empty<T>>,
bool_constant<convertible_to<decltype(ranges::size(declval<T&>()) == 0), bool>>
>>> = true;
template <class T, class = void>
constexpr bool has_begin_compare_to_end = false;
template <class T>
constexpr bool has_begin_compare_to_end<T,
enable_if_t<convertible_to<decltype(ranges::begin(declval<T&>()) == ranges::end(declval<T&>())), bool> >>
= !has_member_empty<T> && !has_size_compare_to_0<T>;
enable_if_t<conjunction_v<
bool_constant<!has_member_empty<T>>,
bool_constant<!has_size_compare_to_0<T>>,
bool_constant<convertible_to<decltype(ranges::begin(declval<T&>()) == ranges::end(declval<T&>())), bool>>
>>> = true;
struct empty_fn
{
template<class T>
[[nodiscard]] constexpr auto operator()(T&& t) const noexcept(noexcept(AZStd::forward<T>(t).empty())) ->
enable_if_t<is_lvalue_or_borrowable<T> && has_member_empty<T>, bool>
enable_if_t<conjunction_v<bool_constant<is_lvalue_or_borrowable<T>>, bool_constant<has_member_empty<T>>>, bool>
{
return AZStd::forward<T>(t).empty();
}
template<class T>
[[nodiscard]] constexpr auto operator()(T&& t) const noexcept(noexcept(ranges::size(AZStd::forward<T>(t)) == 0)) ->
enable_if_t<is_lvalue_or_borrowable<T> && has_size_compare_to_0<T>, bool>
enable_if_t<conjunction_v<bool_constant<is_lvalue_or_borrowable<T>>, bool_constant<has_size_compare_to_0<T>>>, bool>
{
return ranges::size(AZStd::forward<T>(t)) == 0;
}
template<class T>
[[nodiscard]] constexpr auto operator()(T&& t) const noexcept(noexcept(ranges::begin(AZStd::forward<T>(t)) == ranges::end(AZStd::forward<T>(t)))) ->
enable_if_t<is_lvalue_or_borrowable<T> && has_begin_compare_to_end<T>, bool>
enable_if_t<conjunction_v<bool_constant<is_lvalue_or_borrowable<T>>, bool_constant<has_begin_compare_to_end<T>>>, bool>
{
return ranges::begin(AZStd::forward<T>(t)) == ranges::end(AZStd::forward<T>(t));
}
@ -538,14 +588,16 @@ namespace AZStd::ranges
template <class T, class = void>
constexpr bool has_qualified_ranges_begin = false;
template <class T>
constexpr bool has_qualified_ranges_begin<T, enable_if_t<contiguous_iterator<decltype(ranges::begin(declval<T&>()))>> >
= !has_member_data<T>;
constexpr bool has_qualified_ranges_begin<T, enable_if_t<conjunction_v<
bool_constant<!has_member_data<T>>,
bool_constant<contiguous_iterator<decltype(ranges::begin(declval<T&>()))>>
>>> = true;
struct data_fn
{
template<class T>
constexpr auto operator()(T&& t) const noexcept(noexcept(AZStd::forward<T>(t).data())) ->
enable_if_t<is_lvalue_or_borrowable<T> && has_member_data<T>,
enable_if_t<conjunction_v<bool_constant<is_lvalue_or_borrowable<T>>, bool_constant<has_member_data<T>>>,
decltype(AZStd::forward<T>(t).data())>
{
return AZStd::forward<T>(t).data();
@ -553,7 +605,7 @@ namespace AZStd::ranges
template<class T>
constexpr auto operator()(T&& t) const noexcept(noexcept(AZStd::to_address(ranges::begin(AZStd::forward<T>(t))))) ->
enable_if_t<is_lvalue_or_borrowable<T> && has_qualified_ranges_begin<T>,
enable_if_t<conjunction_v<bool_constant<is_lvalue_or_borrowable<T>>, bool_constant<has_qualified_ranges_begin<T>>>,
decltype(AZStd::to_address(ranges::begin(AZStd::forward<T>(t))))>
{
return AZStd::to_address(ranges::begin(AZStd::forward<T>(t)));
@ -612,8 +664,8 @@ namespace AZStd::ranges
// Models borrowed range concept
template<class T>
/*concept*/ constexpr bool borrowed_range = range<T>
&& (is_lvalue_reference_v<T> || enable_borrowed_range<remove_cvref_t<T>>);
/*concept*/ constexpr bool borrowed_range = conjunction_v<bool_constant<range<T>>,
disjunction<is_lvalue_reference<T>, bool_constant<enable_borrowed_range<remove_cvref_t<T>>>>>;
struct dangling
{
@ -622,9 +674,23 @@ namespace AZStd::ranges
constexpr dangling(T&&...) noexcept {}
};
enum class subrange_kind : bool
{
unsized,
sized
};
template<class I, class S = I,
subrange_kind K = sized_sentinel_for<S, I> ? subrange_kind::sized : subrange_kind::unsized,
class = void>
class subrange;
template<class R>
using borrowed_iterator_t = conditional_t<borrowed_range<R>, iterator_t<R>, dangling>;
template<class R>
using borrowed_subrange_t = conditional_t<borrowed_range<R>, subrange<iterator_t<R>>, dangling>;
// Models sized range concept
namespace Internal
{
@ -643,7 +709,11 @@ namespace AZStd::ranges
template<class R, class T, class = void>
constexpr bool output_range_impl = false;
template<class R, class T>
constexpr bool output_range_impl<R, T, enable_if_t<has_iterator_t<R>>> = range<R> && output_iterator<iterator_t<R>, T>;
constexpr bool output_range_impl<R, T, enable_if_t<conjunction_v<
bool_constant<has_iterator_t<R>>,
bool_constant<range<R>>,
bool_constant<output_iterator<iterator_t<R>, T>>
>>> = true;
}
template<class R, class T>
@ -654,7 +724,11 @@ namespace AZStd::ranges
template<class T, class = void>
constexpr bool input_range_impl = false;
template<class T>
constexpr bool input_range_impl<T, enable_if_t<has_iterator_t<T>>> = range<T> && input_iterator<iterator_t<T>>;
constexpr bool input_range_impl<T, enable_if_t<conjunction_v<
bool_constant<has_iterator_t<T>>,
bool_constant<range<T>>,
bool_constant<input_iterator<iterator_t<T>>>
>>> = true;
}
template<class T>
@ -665,7 +739,11 @@ namespace AZStd::ranges
template<class T, class = void>
constexpr bool forward_range_impl = false;
template<class T>
constexpr bool forward_range_impl<T, enable_if_t<has_iterator_t<T>>> = input_range<T> && forward_iterator<iterator_t<T>>;
constexpr bool forward_range_impl<T, enable_if_t<conjunction_v<
bool_constant<has_iterator_t<T>>,
bool_constant<input_range<T>>,
bool_constant<forward_iterator<iterator_t<T>>>
>>> = true;
}
template<class T>
@ -676,7 +754,11 @@ namespace AZStd::ranges
template<class T, class = void>
constexpr bool bidirectional_range_impl = false;
template<class T>
constexpr bool bidirectional_range_impl<T, enable_if_t<has_iterator_t<T>>> = forward_range<T> && bidirectional_iterator<iterator_t<T>>;
constexpr bool bidirectional_range_impl<T, enable_if_t<conjunction_v<
bool_constant<has_iterator_t<T>>,
bool_constant<forward_range<T>>,
bool_constant<bidirectional_iterator<iterator_t<T>>>
>>> = true;
}
template<class T>
@ -687,7 +769,11 @@ namespace AZStd::ranges
template<class T, class = void>
constexpr bool random_access_range_impl = false;
template<class T>
constexpr bool random_access_range_impl<T, enable_if_t<has_iterator_t<T>>> = bidirectional_range<T> && random_access_iterator<iterator_t<T>>;
constexpr bool random_access_range_impl<T, enable_if_t<conjunction_v<
bool_constant<has_iterator_t<T>>,
bool_constant<bidirectional_range<T>>,
bool_constant<random_access_iterator<iterator_t<T>>>
>>> = true;
}
template<class T>
@ -710,16 +796,19 @@ namespace AZStd::ranges
template<class T, class = void>
constexpr bool contiguous_range_impl = false;
template<class T>
constexpr bool contiguous_range_impl<T, enable_if_t<random_access_range<T>
&& contiguous_iterator<iterator_t<T>>
&& same_as<decltype(ranges::data(declval<T&>())), add_pointer_t<range_reference_t<T>>> >> = true;
constexpr bool contiguous_range_impl<T, enable_if_t<conjunction_v<
bool_constant<random_access_range<T>>,
bool_constant<contiguous_iterator<iterator_t<T>>>,
bool_constant<same_as<decltype(ranges::data(declval<T&>())), add_pointer_t<range_reference_t<T>>>>
>>> = true;
}
template<class T>
/*concept*/ constexpr bool contiguous_range = Internal::contiguous_range_impl<T>;
template<class T>
/*concept*/ constexpr bool common_range = range<T> && same_as<iterator_t<T>, sentinel_t<T>>;
/*concept*/ constexpr bool common_range = conjunction_v<bool_constant<range<T>>,
bool_constant<same_as<iterator_t<T>, sentinel_t<T>>>>;
}
namespace AZStd::ranges
@ -752,7 +841,7 @@ namespace AZStd::ranges
template<class I, class S>
constexpr auto operator()(I& i, S bound) const ->
enable_if_t<input_or_output_iterator<I>&& sentinel_for<S, I>>
enable_if_t<conjunction_v<bool_constant<input_or_output_iterator<I>>, bool_constant<sentinel_for<S, I>>>>
{
if constexpr (assignable_from<I&, S>)
{
@ -770,7 +859,8 @@ namespace AZStd::ranges
template<class I, class S>
constexpr auto operator()(I& i, iter_difference_t<I> n, S bound) const ->
enable_if_t<input_or_output_iterator<I>&& sentinel_for<S, I>, iter_difference_t<I>>
enable_if_t<conjunction_v<bool_constant<input_or_output_iterator<I>>, bool_constant<sentinel_for<S, I>>>,
iter_difference_t<I>>
{
if constexpr (sized_sentinel_for<S, I>)
{
@ -816,7 +906,9 @@ namespace AZStd::ranges
{
template<class I, class S>
constexpr auto operator()(I first, S last) const ->
enable_if_t<input_or_output_iterator<I> && sentinel_for<S, I> && !sized_sentinel_for<S, I>,
enable_if_t<conjunction_v<bool_constant<input_or_output_iterator<I>>,
bool_constant<sentinel_for<S, I>>,
bool_constant<!sized_sentinel_for<S, I>>>,
iter_difference_t<I>>
{
// Since S is not a sized sentinel, can only increment from first to last
@ -828,7 +920,9 @@ namespace AZStd::ranges
template<class I, class S>
constexpr auto operator()(const I& first, const S& last) const ->
enable_if_t<input_or_output_iterator<I> && sentinel_for<S, I> && sized_sentinel_for<S, I>,
enable_if_t<conjunction_v<bool_constant<input_or_output_iterator<I>>,
bool_constant<sentinel_for<S, I>>,
bool_constant<sized_sentinel_for<S, I>>>,
iter_difference_t<I>>
{
return last - first;
@ -878,7 +972,7 @@ namespace AZStd::ranges
template<class I, class S>
constexpr auto operator()(I x, S bound) const ->
enable_if_t<input_or_output_iterator<I>&& sentinel_for<S, I>, I>
enable_if_t<conjunction_v<bool_constant<input_or_output_iterator<I>>, bool_constant<sentinel_for<S, I>>>, I>
{
ranges::advance(x, bound);
return x;
@ -886,7 +980,7 @@ namespace AZStd::ranges
template<class I, class S>
constexpr auto operator()(I x, iter_difference_t<I> n, S bound) const ->
enable_if_t<input_or_output_iterator<I>&& sentinel_for<S, I>, I>
enable_if_t<conjunction_v<bool_constant<input_or_output_iterator<I>>, bool_constant<sentinel_for<S, I>>>, I>
{
ranges::advance(x, n, bound);
return x;
@ -922,7 +1016,7 @@ namespace AZStd::ranges
template<class I, class S>
constexpr auto operator()(I x, iter_difference_t<I> n, S bound) const ->
enable_if_t<input_or_output_iterator<I>&& sentinel_for<S, I>, I>
enable_if_t<conjunction_v<bool_constant<input_or_output_iterator<I>>, bool_constant<sentinel_for<S, I>>>, I>
{
ranges::advance(x, -n, bound);
return x;
@ -950,16 +1044,51 @@ namespace AZStd::ranges
// view interface can be used with non-constant class types
template<class D, class = void>
class view_interface;
struct view_base {};
namespace Internal
{
template<class D>
void derived_from_view_interface_template(view_interface<D>&);
template<class T, class = void>
inline constexpr bool is_derived_from_view_interface = false;
template<class T>
inline constexpr bool is_derived_from_view_interface<T,
decltype(derived_from_view_interface_template(declval<remove_cvref_t<T>&>()))> = true;
}
template<class T>
inline constexpr bool enable_view = derived_from<T, view_base> || Internal::is_derived_from_view_interface<T>;
template<class T>
/*concept*/ constexpr bool view = conjunction_v<bool_constant<range<T>>, bool_constant<movable<T>>, bool_constant<enable_view<T>>>;
template<class T>
/*concept*/ constexpr bool viewable_range = conjunction_v<bool_constant<range<T>>,
disjunction<
conjunction<bool_constant<view<remove_cvref_t<T>>>, bool_constant<constructible_from<remove_cvref_t<T>, T>>>,
conjunction<bool_constant<!view<remove_cvref_t<T>>>,
disjunction<is_lvalue_reference<T>,
conjunction<bool_constant<movable<remove_reference_t<T>>>,
bool_constant<!Internal::is_initializer_list<T>>
>
>
>
>
>;
template<class D>
class view_interface< D, enable_if_t<is_class_v<D> && same_as<D, remove_cv_t<D>> >>
class view_interface<D, enable_if_t<is_class_v<D> && same_as<D, remove_cv_t<D>> >>
{
private:
constexpr D& derived() noexcept
{
// Make sure that the derived type is complete
static_assert(sizeof(D) > 0 && derived_from<D, view_interface> && view<D>);
return static_cast<D&>(*this);
}
constexpr const D& derived() const noexcept
{
static_assert(sizeof(D) > 0 && derived_from<D, view_interface> && view<D>);
return static_cast<const D&>(*this);
}
@ -975,134 +1104,141 @@ namespace AZStd::ranges
return ranges::begin(derived()) == ranges::end(derived());
}
template <class Derived = D, class = void_t<decltype(ranges::empty(declval<Derived>()))>>
constexpr explicit operator bool() const noexcept(noexcept(ranges::empty(derived())))
template <class Derived = D>
constexpr explicit operator bool() const noexcept(noexcept(ranges::empty(static_cast<const Derived&>(*this))))
{
return !ranges::empty(derived());
}
template <class Derived = D>
constexpr auto data() ->
enable_if_t<contiguous_iterator<iterator_t<Derived>>, decltype(to_address(ranges::begin(derived())))>
enable_if_t<contiguous_iterator<iterator_t<Derived>>, decltype(to_address(ranges::begin(static_cast<Derived&>(*this))))>
{
return to_address(ranges::begin(derived()));
}
template <class Derived = D>
constexpr auto data() const ->
enable_if_t<contiguous_iterator<iterator_t<const Derived>>, decltype(to_address(ranges::begin(derived())))>
enable_if_t<range<const Derived> && contiguous_iterator<iterator_t<const Derived>>,
decltype(to_address(ranges::begin(static_cast<const Derived&>(*this))))>
{
return to_address(ranges::begin(derived()));
}
template <class Derived = D>
constexpr auto size() ->
enable_if_t<forward_range<Derived> && sized_sentinel_for<sentinel_t<Derived>, iterator_t<Derived>>,
decltype(ranges::end(derived()) - ranges::begin(derived()))>
enable_if_t<conjunction_v<bool_constant<forward_range<Derived>>,
bool_constant<sized_sentinel_for<sentinel_t<Derived>, iterator_t<Derived>>>>,
decltype(ranges::end(static_cast<Derived&>(*this)) - ranges::begin(static_cast<Derived&>(*this)))>
{
return ranges::end(derived()) - ranges::begin(derived());
}
template <class Derived = D>
constexpr auto size() const ->
enable_if_t<forward_range<const Derived>&& sized_sentinel_for<sentinel_t<const Derived>, iterator_t<const Derived>>,
decltype(ranges::end(derived()) - ranges::begin(derived()))>
enable_if_t<conjunction_v<bool_constant<forward_range<const Derived>>,
bool_constant<sized_sentinel_for<sentinel_t<const Derived>, iterator_t<const Derived>>>>,
decltype(ranges::end(static_cast<const Derived&>(*this)) - ranges::begin(static_cast<const Derived&>(*this)))>
{
return ranges::end(derived()) - ranges::begin(derived());
}
template <class Derived = D>
constexpr auto front() ->
enable_if_t<forward_range<Derived>, decltype(*ranges::begin(derived()))>
enable_if_t<forward_range<Derived>, decltype(*ranges::begin(static_cast<Derived&>(*this)))>
{
return *ranges::begin(derived());
}
template <class Derived = D>
constexpr auto front() const ->
enable_if_t<forward_range<const Derived>, decltype(*ranges::begin(derived()))>
enable_if_t<forward_range<const Derived>, decltype(*ranges::begin(static_cast<const Derived&>(*this)))>
{
return *ranges::begin(derived());
}
template <class Derived = D>
constexpr auto back() ->
enable_if_t<bidirectional_range<Derived> && common_range<Derived>, decltype(*ranges::prev(ranges::end(derived())))>
enable_if_t<conjunction_v<bool_constant<bidirectional_range<Derived>>,
bool_constant<common_range<Derived>>>,
decltype(*ranges::prev(ranges::end(static_cast<Derived&>(*this))))>
{
return *ranges::prev(ranges::end(derived()));
}
template <class Derived = D>
constexpr auto back() const ->
enable_if_t<bidirectional_range<const Derived>&& common_range<const Derived>, decltype(*ranges::prev(ranges::end(derived())))>
enable_if_t<conjunction_v<bool_constant<bidirectional_range<const Derived>>,
bool_constant<common_range<const Derived>>>,
decltype(*ranges::prev(ranges::end(static_cast<const Derived&>(*this))))>
{
return *ranges::prev(ranges::end(derived()));
}
template<class R = D>
constexpr auto operator[](range_difference_t<R> n) ->
enable_if_t<random_access_range<R>, decltype(ranges::begin(derived())[n])>
enable_if_t<random_access_range<R>, decltype(ranges::begin(static_cast<R&>(*this))[n])>
{
return ranges::begin(derived())[n];
}
template<class R = const D>
constexpr auto operator[](range_difference_t<R> n) const ->
enable_if_t<random_access_range<R>, decltype(ranges::begin(derived())[n])>
enable_if_t<random_access_range<R>, decltype(ranges::begin(static_cast<R&>(*this))[n])>
{
return ranges::begin(derived())[n];
}
};
struct view_base {};
// Helper Concepts - https://eel.is/c++draft/ranges#range.utility.helpers
namespace Internal
{
template<class D>
void derived_from_view_interface_template(view_interface<D>&);
template<class T, class = void>
inline constexpr bool is_derived_from_view_interface = false;
template<class T>
inline constexpr bool is_derived_from_view_interface<T,
decltype(derived_from_view_interface_template(declval<T&>()))> = true;
// Helper concepts that are used by range adaptor classes
template<bool Const, class T>
using maybe_const = conditional_t<Const, const T, T>;
template<class R, class = void>
/*concept*/ constexpr bool simple_view = false;
template<class R>
/*concept*/ inline constexpr bool simple_view<R, enable_if_t<conjunction_v<
bool_constant<view<R>>,
bool_constant<range<const R>>,
bool_constant<same_as<iterator_t<R>, iterator_t<const R>>>,
bool_constant<same_as<sentinel_t<R>, sentinel_t<const R>>> >>> = true;
template<class I, class = void>
/*concept*/ constexpr bool has_arrow = false;
template<class I>
/*concept*/ inline constexpr bool has_arrow<I, enable_if_t<conjunction_v<
bool_constant<input_iterator<I>>,
disjunction<is_pointer<I>, sfinae_trigger<decltype(declval<I>().operator->())>>
>>> = true;
template<class T, class U>
/*concept*/ constexpr bool different_from = !same_as<remove_cvref_t<T>, remove_cvref_t<U>>;
}
template<class T>
inline constexpr bool enable_view = derived_from<T, view_base> || Internal::is_derived_from_view_interface<T>;
template<class T>
/*concept*/ constexpr bool view = range<T> && movable<T> && enable_view<T>;
template<class T>
/*concept*/ constexpr bool viewable_range = range<T> &&
((view<remove_cvref_t<T>> && constructible_from<remove_cvref_t<T>, T>) ||
(!view<remove_cvref_t<T>> &&
(is_lvalue_reference_v<T> || (movable<remove_reference_t<T>> && !Internal::is_initializer_list<T>))));
}
namespace AZStd::ranges
{
#if __has_cpp_attribute(no_unique_address)
#define az_no_unique_address [[no_unique_address]]
#else
#define az_no_unique_address
#endif
template<class I1, class I2>
struct in_in_result
{
az_no_unique_address I1 in1;
az_no_unique_address I2 in2;
AZ_NO_UNIQUE_ADDRESS I1 in1;
AZ_NO_UNIQUE_ADDRESS I2 in2;
template<class II1, class II2, class = enable_if_t<convertible_to<const I1&, II1>&& convertible_to<const I2&, II2>> >
template<class II1, class II2, class = enable_if_t<conjunction_v<
bool_constant<convertible_to<const I1&, II1>>, bool_constant<convertible_to<const I2&, II2>>>> >
constexpr operator in_in_result<II1, II2>() const&
{
return { in1, in2 };
}
template<class II1, class II2, class = enable_if_t<convertible_to<I1, II1>&& convertible_to<I2, II2>> >
template<class II1, class II2, class = enable_if_t<conjunction_v<
bool_constant<convertible_to<I1, II1>>, bool_constant<convertible_to<I2, II2>>>> >
constexpr operator in_in_result<II1, II2>()&&
{
return { AZStd::move(in1), AZStd::move(in2) };
}
};
#undef az_no_unique_address
template<class I1, class I2>
using swap_ranges_result = in_in_result<I1, I2>;
@ -1112,9 +1248,11 @@ namespace AZStd::ranges
{
template<class I1, class S1, class I2, class S2>
constexpr auto operator()(I1 first1, S1 last1, I2 first2, S2 last2) const ->
enable_if_t<input_iterator<I1>&& sentinel_for<S1, I1>
&& input_iterator<I2>&& sentinel_for<S2, I2>
&& indirectly_swappable<I1, I2>,
enable_if_t<conjunction_v<bool_constant<input_iterator<I1>>,
bool_constant<sentinel_for<S1, I1>>,
bool_constant<input_iterator<I2>>,
bool_constant<sentinel_for<S2, I2>>,
bool_constant<indirectly_swappable<I1, I2>>>,
swap_ranges_result<I1, I2>>
{
for (; !(first1 == last1 or first2 == last2); ++first1, ++first2)
@ -1126,8 +1264,10 @@ namespace AZStd::ranges
template<class R1, class R2>
constexpr auto operator()(R1&& r1, R2&& r2) const ->
enable_if_t<input_range<R1>&& input_range<R2>
&& indirectly_swappable<iterator_t<R1>, iterator_t<R2>>,
enable_if_t<conjunction_v<
bool_constant<input_range<R1>>,
bool_constant<input_range<R2>>,
bool_constant<indirectly_swappable<iterator_t<R1>, iterator_t<R2>>>>,
swap_ranges_result<borrowed_iterator_t<R1>, borrowed_iterator_t<R2>>>
{
return operator()(ranges::begin(r1), ranges::end(r1),
@ -1148,10 +1288,21 @@ namespace AZStd::ranges::Internal
// ranges::swap customization point https://eel.is/c++draft/concepts#concept.swappable-2.2
template <class T, class U>
constexpr auto swap_fn::operator()(T&& t, U&& u) const noexcept(noexcept((*this)(*t, *u)))
->enable_if_t<!is_class_or_enum_with_swap_adl<T, U>
&& is_array_v<T> && is_array_v<U> && (extent_v<T> == extent_v<U>)
>
->enable_if_t<conjunction_v<
bool_constant<!is_class_or_enum_with_swap_adl<T, U>>,
is_array<T>,
is_array<U>,
bool_constant<extent_v<T> == extent_v<U>>
>>
{
ranges::swap_ranges(t, u);
}
}
// Opening AZStd::ranges::views namespace to provide access to it in AZStd
namespace AZStd::ranges::views{}
namespace AZStd
{
namespace views = ranges::views;
}

@ -0,0 +1,333 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/std/ranges/ranges.h>
#include <AzCore/std/optional.h>
namespace AZStd::ranges::views::Internal
{
// Call wrapping that performs perfecting forwarding of arguments
// and take const and ref function qualifiers into account(rvalue functions will move)
template<class Outer, class Inner>
struct perfect_forwarding_call_wrapper
{
perfect_forwarding_call_wrapper(Outer&& outer, Inner&& inner)
: m_outer{ AZStd::forward<Outer>(outer) }
, m_inner{ AZStd::forward<Inner>(inner) }
{}
template<class... Args>
constexpr decltype(auto) operator()(Args&&... args) &
noexcept(noexcept(AZStd::invoke(m_outer, AZStd::invoke(m_inner, AZStd::forward<Args>(args)...))))
{
return AZStd::invoke(m_outer, AZStd::invoke(m_inner, AZStd::forward<Args>(args)...));
}
template<class... Args>
constexpr decltype(auto) operator()(Args&&... args) const&
noexcept(noexcept(AZStd::invoke(m_outer, AZStd::invoke(m_inner, AZStd::forward<Args>(args)...))))
{
return AZStd::invoke(m_outer, AZStd::invoke(m_inner, AZStd::forward<Args>(args)...));
}
//
template<class... Args>
constexpr decltype(auto) operator()(Args&&... args) &&
noexcept(noexcept(AZStd::invoke(AZStd::move(m_outer),
AZStd::invoke(AZStd::move(m_inner), AZStd::forward<Args>(args)...))))
{
return AZStd::invoke(AZStd::move(m_outer), AZStd::invoke(AZStd::move(m_inner), AZStd::forward<Args>(args)...));
}
template<class... Args>
constexpr decltype(auto) operator()(Args&&... args) const&&
noexcept(noexcept(AZStd::invoke(AZStd::move(m_outer),
AZStd::invoke(AZStd::move(m_inner), AZStd::forward<Args>(args)...))))
{
return AZStd::invoke(AZStd::move(m_outer), AZStd::invoke(AZStd::move(m_inner), AZStd::forward<Args>(args)...));
}
private:
Outer m_outer;
Inner m_inner;
};
// base class which provides the bitwise OR operator to
// any derived classes
// This can be used by inherited by range adaptor classes
// to implement their to allow for changing
// https://eel.is/c++draft/ranges#range.adaptor.object-1.3
template<class RangeAdaptor>
struct range_adaptor_closure;
// Return a closure new in which the outer range adaptor invokes the inner range adaptor
template<class RangeAdaptorFunctor>
struct range_adaptor_closure_forwarder
: RangeAdaptorFunctor
, range_adaptor_closure_forwarder<range_adaptor_closure<RangeAdaptorFunctor>>
{
constexpr explicit range_adaptor_closure_forwarder(RangeAdaptorFunctor&& closure)
: RangeAdaptorFunctor{ AZStd::forward<RangeAdaptorFunctor>(closure) }
{}
};
template<class RangeAdaptor>
using is_range_closure_t = bool_constant<derived_from<remove_cvref_t<RangeAdaptor>,
range_adaptor_closure<remove_cvref_t<RangeAdaptor>>>>;
template<class T>
struct range_adaptor_closure
{
template<class View, class U>
friend constexpr auto operator|(View&& view, U&& closure) noexcept(is_nothrow_invocable_v<View, U>)
-> enable_if_t<conjunction_v<
bool_constant<viewable_range<View>>,
is_range_closure_t<U>,
bool_constant<same_as<T, remove_cvref_t<U>>>,
bool_constant<invocable<U, View>>>,
decltype(AZStd::invoke(AZStd::forward<U>(closure), AZStd::forward<View>(view)))>
{
return AZStd::invoke(AZStd::forward<U>(closure), AZStd::forward<View>(view));
}
template<class U, class Target>
friend constexpr auto operator|(U&& closure, Target&& outerClosure)
noexcept(is_nothrow_constructible_v<remove_cvref_t<U>> && is_nothrow_constructible_v<remove_cvref_t<Target>>)
->enable_if_t<conjunction_v<
is_range_closure_t<U>,
is_range_closure_t<Target>,
bool_constant<same_as<T, remove_cvref_t<U>>>,
bool_constant<constructible_from<decay_t<U>, U>>,
bool_constant<constructible_from<decay_t<Target>, Target>>>,
decltype(range_adaptor_closure_forwarder{
perfect_forwarding_call_wrapper{AZStd::forward<Target>(outerClosure), AZStd::forward<U>(closure) }
})>
{
// Create a perfect_forwarding_wrapper that wraps the outer adaptor around the inner adaptor
// and then pass that to the range_adaptor_closure_forward struct which inherits from
// range_adaptor_closure class template so that it is_range_closure_t template succeeds
return range_adaptor_closure_forwarder{
perfect_forwarding_call_wrapper{AZStd::forward<Target>(outerClosure), AZStd::forward<U>(closure) }
};
}
};
} // namespace AZStd::ranges::views::Internal
namespace AZStd::ranges::Internal
{
// Copyable Wrapper - https://eel.is/c++draft/ranges#range.copy.wrap
// Used to wrap a class that copy constructible, but not necessarily copy assignable
// and implements a copy assignment operator using the optional emplace function
// to construct in place
template<class T, class = void>
class copyable_box;
template<class T>
class copyable_box<T, enable_if_t<is_copy_constructible_v<T>&& is_object_v<T>>>
{
public:
template<class U = T, class = enable_if_t<default_initializable<U>>>
constexpr copyable_box() noexcept(is_nothrow_constructible_v<T>)
: copyable_box{ in_place }
{}
template<class... Args>
explicit constexpr copyable_box(in_place_t, Args&&... args) noexcept(is_nothrow_constructible_v<T>)
: m_copyable_wrapper{ in_place, AZStd::forward<Args>(args)... }
{}
constexpr copyable_box(const copyable_box&) = default;
constexpr copyable_box(copyable_box&&) = default;
constexpr copyable_box& operator=(const copyable_box& other) noexcept(is_nothrow_copy_constructible_v<T>)
{
if (this != &other)
{
if constexpr (copyable<T>)
{
m_copyable_wrapper = other.m_copyable_wrapper;
}
else
{
if (other)
{
emplace(other.m_copyable_wrapper);
}
else
{
reset();
}
}
}
return *this;
}
constexpr copyable_box& operator=(copyable_box&& other) noexcept(is_nothrow_move_constructible_v<T>)
{
if (this != &other)
{
if constexpr (movable<T>)
{
m_copyable_wrapper = AZStd::move(other.m_copyable_wrapper);
}
else
{
if (other)
{
emplace(AZStd::move(other.m_copyable_wrapper));
}
else
{
reset();
}
}
}
return *this;
}
constexpr T& operator*() & noexcept
{
return *m_copyable_wrapper;
}
constexpr const T& operator*() const& noexcept
{
return *m_copyable_wrapper;
}
constexpr T&& operator*() && noexcept
{
return AZStd::move(*m_copyable_wrapper);
}
constexpr const T&& operator*() const&& noexcept
{
return AZStd::move(*m_copyable_wrapper);
}
constexpr T* operator->() noexcept
{
return m_copyable_wrapper.operator->();
}
constexpr const T* operator->() const noexcept
{
return m_copyable_wrapper.operator->();
}
constexpr explicit operator bool()
{
return m_copyable_wrapper.has_value();
}
template<class... Args>
constexpr T& emplace(Args&&... args)
{
return m_copyable_wrapper.emplace(AZStd::forward<Args>(args)...);
}
constexpr void reset() noexcept
{
m_copyable_wrapper.reset();
}
private:
optional<T> m_copyable_wrapper;
};
// Non-propagating cache - https://eel.is/c++draft/ranges#range.nonprop.cache
// Enables an input view to temporarily cache values over as it is iterated over.
// For copy construction, a current instance is default initialized
// For move construction, the input object is reset
// On copy assignment, the current instance is reset
// Onmove assignment, both the current and input are reset
template<class T, class = void>
class non_propagating_cache;
template<class T>
class non_propagating_cache<T, enable_if_t<is_object_v<T>>>
{
public:
template<class U = T, class = enable_if_t<default_initializable<U>>>
constexpr non_propagating_cache() noexcept(is_nothrow_constructible_v<T>)
: non_propagating_cache{ in_place }
{}
template<class... Args>
explicit constexpr non_propagating_cache(in_place_t, Args&&... args) noexcept
: m_cache{ in_place, AZStd::forward<Args>(args)... }
{}
// Purposely does not initialize the wrapper
constexpr non_propagating_cache(const non_propagating_cache&)
{}
constexpr non_propagating_cache(non_propagating_cache&& other)
{
other.reset();
}
constexpr auto operator=(const non_propagating_cache& other) noexcept
{
if (this != &other)
{
reset();
}
return *this;
}
constexpr auto operator=(non_propagating_cache&& other) noexcept
{
reset();
other.reset();
return *this;
}
constexpr T& operator*() & noexcept
{
return *m_cache;
}
constexpr const T& operator*() const& noexcept
{
return *m_cache;
}
constexpr T&& operator*() && noexcept
{
return AZStd::move(*m_cache);
}
constexpr const T&& operator*() const&& noexcept
{
return AZStd::move(*m_cache);
}
constexpr T* operator->() noexcept
{
return m_cache.operator->();
}
constexpr const T* operator->() const noexcept
{
return m_cache.operator->();
}
constexpr explicit operator bool()
{
return m_cache.has_value();
}
template<class... Args>
constexpr T& emplace(Args&&... args)
{
return m_cache.emplace(AZStd::forward<Args>(args)...);
}
template<class I>
constexpr auto emplace_deref(const I& i) -> enable_if_t<constructible_from<T, decltype(*i)>, T&>
{
return m_cache.emplace(*i);
}
constexpr void reset() noexcept
{
m_cache.reset();
}
private:
optional<T> m_cache;
};
} // namespace AZStd::ranges::Internal

@ -0,0 +1,996 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/std/function/identity.h>
#include <AzCore/std/ranges/ranges.h>
#include <AzCore/std/ranges/ranges_functional.h>
#include <AzCore/std/ranges/subrange.h>
namespace AZStd::ranges
{
template<class T>
struct min_max_result
{
AZ_NO_UNIQUE_ADDRESS T min;
AZ_NO_UNIQUE_ADDRESS T max;
template<class T2, class = enable_if_t<convertible_to<const T&, T2>>>
constexpr operator min_max_result<T2>() const&
{
return { min, max };
}
template<class T2, class = enable_if_t<convertible_to<T, T2>>>
constexpr operator min_max_result<T2>()&&
{
return { std::move(min), std::move(max) };
}
};
template<class T>
using minmax_result = min_max_result<T>;
template<class I>
using minmax_element_result = min_max_result<I>;
namespace Internal
{
struct min_fn
{
template<class T, class Proj = identity, class Comp = ranges::less>
constexpr auto operator()(const T& a, const T& b, Comp comp = {}, Proj proj = {}) const
-> enable_if_t<indirect_strict_weak_order<Comp, projected<const T*, Proj>>, const T&>
{
return AZStd::invoke(comp, AZStd::invoke(proj, b), AZStd::invoke(proj, a)) ? b : a;
}
template<class T, class Proj = identity, class Comp = ranges::less>
constexpr auto operator()(initializer_list<T> r, Comp comp = {}, Proj proj = {}) const
->enable_if_t<conjunction_v<
bool_constant<copyable<T>>,
bool_constant<indirect_strict_weak_order<Comp, projected<const T*, Proj>>>>, T>
{
AZ_Assert(r.size() > 0, "ranges::min cannot be invoked with an empty initializer_list");
auto it = r.begin();
auto last = r.end();
T result{ *it };
for (; it != last; ++it)
{
if (AZStd::invoke(comp, AZStd::invoke(proj, *it), AZStd::invoke(proj, result)))
{
result = *it;
}
}
return result;
}
template<class R, class Proj = identity, class Comp = ranges::less>
constexpr auto operator()(R&& r, Comp comp = {}, Proj proj = {}) const
->enable_if_t<conjunction_v<
bool_constant<input_range<R>>,
bool_constant<indirect_strict_weak_order<Comp, projected<iterator_t<R>, Proj>>>,
bool_constant<indirectly_copyable_storable<iterator_t<R>, range_value_t<R>*>>>, range_value_t<R>>
{
AZ_Assert(ranges::distance(r) > 0, "ranges::min cannot be invoked with an empty range");
auto it = ranges::begin(r);
auto last = ranges::end(r);
range_value_t<R> result{ *it };
for (; it != last; ++it)
{
if (AZStd::invoke(comp, AZStd::invoke(proj, *it), AZStd::invoke(proj, result)))
{
result = *it;
}
}
return result;
}
};
} // namespace Internal
inline namespace customization_point_object
{
constexpr Internal::min_fn min{};
}
namespace Internal
{
struct max_fn
{
template<class T, class Proj = identity, class Comp = ranges::less>
constexpr auto operator()(const T& a, const T& b, Comp comp = {}, Proj proj = {}) const
-> enable_if_t<indirect_strict_weak_order<Comp, projected<const T*, Proj>>, const T&>
{
return AZStd::invoke(comp, AZStd::invoke(proj, a), AZStd::invoke(proj, b)) ? b : a;
}
template<class T, class Proj = identity, class Comp = ranges::less>
constexpr auto operator()(initializer_list<T> r, Comp comp = {}, Proj proj = {}) const
->enable_if_t<conjunction_v<
bool_constant<copyable<T>>,
bool_constant<indirect_strict_weak_order<Comp, projected<const T*, Proj>>>>, T>
{
AZ_Assert(r.size() > 0, "ranges::max cannot be invoked with an empty initializer_list");
auto it = r.begin();
auto last = r.end();
T result{ *it };
for (; it != last; ++it)
{
if (AZStd::invoke(comp, AZStd::invoke(proj, result), AZStd::invoke(proj, *it)))
{
result = *it;
}
}
return result;
}
template<class R, class Proj = identity, class Comp = ranges::less>
constexpr auto operator()(R&& r, Comp comp = {}, Proj proj = {}) const
->enable_if_t<conjunction_v<
bool_constant<input_range<R>>,
bool_constant<indirect_strict_weak_order<Comp, projected<iterator_t<R>, Proj>>>,
bool_constant<indirectly_copyable_storable<iterator_t<R>, range_value_t<R>*>>>, range_value_t<R>>
{
AZ_Assert(ranges::distance(r) > 0, "ranges::max cannot be invoked with an empty range");
auto it = ranges::begin(r);
auto last = ranges::end(r);
range_value_t<R> result{ *it };
for (; it != last; ++it)
{
if (AZStd::invoke(comp, AZStd::invoke(proj, result), AZStd::invoke(proj, *it)))
{
result = *it;
}
}
return result;
}
};
} // namespace Internal
inline namespace customization_point_object
{
constexpr Internal::max_fn max{};
}
namespace Internal
{
struct minmax_fn
{
template<class T, class Proj = identity, class Comp = ranges::less>
constexpr auto operator()(const T& a, const T& b, Comp comp = {}, Proj proj = {}) const
-> enable_if_t<indirect_strict_weak_order<Comp, projected<const T*, Proj>>, minmax_result<const T&>>
{
return AZStd::invoke(comp, AZStd::invoke(proj, b), AZStd::invoke(proj, a)) ?
minmax_result<const T&>{b, a} : minmax_result<const T&>{a, b};
}
template<class T, class Proj = identity, class Comp = ranges::less>
constexpr auto operator()(initializer_list<T> r, Comp comp = {}, Proj proj = {}) const
->enable_if_t<conjunction_v<
bool_constant<copyable<T>>,
bool_constant<indirect_strict_weak_order<Comp, projected<const T*, Proj>>>>,
minmax_result<T>>
{
AZ_Assert(r.size() > 0, "ranges::minmax cannot be invoked with an empty initializer_list");
auto first = r.begin();
minmax_result<T> result{ *first, *first };
auto last = r.end();
for (; first != last; ++first)
{
// Algorithm requires at most (3/2 * ranges::distance(r)) comparisons
if (auto prevIt = first++; first == last)
{
// Find the leftmost smallest element
if (AZStd::invoke(comp, AZStd::invoke(proj, *prevIt), AZStd::invoke(proj, result.min)))
{
result.min = *prevIt;
}
// Find the rightmost largest element
else if (!AZStd::invoke(comp, AZStd::invoke(proj, *prevIt), AZStd::invoke(proj, result.max)))
{
result.max = *prevIt;
}
break;
}
else
{
// For every two elements performs a transitive comparisons to calculate either new
// leftmost min or rightmost max using at most three comparisons
// (*first < *prevIt) && (*first < result.min), then *first = leftmost min
// (*first < *prevIt) && (*prevIt >= result.max), then *prevIt = rightmost max
// else
// (*first >= *prevIt) && (*prevIt < result.min), then *prevIt = leftmost min
// (*first >= *prevIt) && (*first >= result.max), then *first = rightmost max
if (AZStd::invoke(comp, AZStd::invoke(proj, *first), AZStd::invoke(proj, *prevIt)))
{
if (AZStd::invoke(comp, AZStd::invoke(proj, *first), AZStd::invoke(proj, result.min)))
{
result.min = *first;
}
if (!AZStd::invoke(comp, AZStd::invoke(proj, *prevIt), AZStd::invoke(proj, result.max)))
{
result.max = *prevIt;
}
}
else
{
if (AZStd::invoke(comp, AZStd::invoke(proj, *prevIt), AZStd::invoke(proj, result.min)))
{
result.min = *prevIt;
}
if (!AZStd::invoke(comp, AZStd::invoke(proj, *first), AZStd::invoke(proj, result.max)))
{
result.max = *first;
}
}
}
}
return result;
}
template<class R, class Proj = identity, class Comp = ranges::less>
constexpr auto operator()(R&& r, Comp comp = {}, Proj proj = {}) const
-> enable_if_t<conjunction_v<
bool_constant<input_range<R>>,
bool_constant<indirect_strict_weak_order<Comp, projected<iterator_t<R>, Proj>>>,
bool_constant<indirectly_copyable_storable<iterator_t<R>, range_value_t<R>*>>>,
minmax_result<range_value_t<R>>>
{
AZ_Assert(ranges::distance(r) > 0, "ranges::minmax cannot be invoked with an empty range");
auto first = ranges::begin(r);
minmax_result<range_value_t<R>> result{ *first, *first };
auto last = ranges::end(r);
for (; first != last; ++first)
{
// Algorithm requires at most (3/2 * ranges::distance(r)) comparisons
if (auto prevIt = first++; first == last)
{
// Find the leftmost smallest element
if (AZStd::invoke(comp, AZStd::invoke(proj, *prevIt), AZStd::invoke(proj, result.min)))
{
result.min = *prevIt;
}
// Find the rightmost largest element
else if (!AZStd::invoke(comp, AZStd::invoke(proj, *prevIt), AZStd::invoke(proj, result.max)))
{
result.max = *prevIt;
}
break;
}
else
{
// For every two elements performs a transitive comparisons to calculate either new
// leftmost min or rightmost max using at most three comparisons
// (*first < *prevIt) && (*first < result.min), then *first = leftmost min
// (*first < *prevIt) && (*prevIt >= result.max), then *prevIt = rightmost max
// else
// (*first >= *prevIt) && (*prevIt < result.min), then *prevIt = leftmost min
// (*first >= *prevIt) && (*first >= result.max), then *first = rightmost max
if (AZStd::invoke(comp, AZStd::invoke(proj, *first), AZStd::invoke(proj, *prevIt)))
{
if (AZStd::invoke(comp, AZStd::invoke(proj, *first), AZStd::invoke(proj, result.min)))
{
result.min = *first;
}
if (!AZStd::invoke(comp, AZStd::invoke(proj, *prevIt), AZStd::invoke(proj, result.max)))
{
result.max = *prevIt;
}
}
else
{
if (AZStd::invoke(comp, AZStd::invoke(proj, *prevIt), AZStd::invoke(proj, result.min)))
{
result.min = *prevIt;
}
if (!AZStd::invoke(comp, AZStd::invoke(proj, *first), AZStd::invoke(proj, result.max)))
{
result.max = *first;
}
}
}
}
return result;
}
};
}
inline namespace customization_point_object
{
constexpr Internal::minmax_fn minmax{};
}
namespace Internal
{
struct min_element_fn
{
template<class I, class S, class Proj = identity, class Comp = ranges::less>
constexpr auto operator()(I first, S last, Comp comp = {}, Proj proj = {}) const
-> enable_if_t<conjunction_v<
bool_constant<forward_iterator<I>>,
bool_constant<sentinel_for<S, I>>,
bool_constant<indirect_strict_weak_order<Comp, projected<I, Proj>>>
>, I>
{
I result{ first };
for (; first != last; ++first)
{
if (AZStd::invoke(comp, AZStd::invoke(proj, *first), AZStd::invoke(proj, *result)))
{
result = first;
}
}
return result;
}
template<class R, class Proj = identity, class Comp = ranges::less>
constexpr auto operator()(R&& r, Comp comp = {}, Proj proj = {}) const
->enable_if_t<conjunction_v<
bool_constant<forward_range<R>>,
bool_constant<indirect_strict_weak_order<Comp, projected<iterator_t<R>, Proj>>>
>, borrowed_iterator_t<R>>
{
auto it = ranges::begin(r);
auto last = ranges::end(r);
borrowed_iterator_t<R> result{ it };
for (; it != last; ++it)
{
if (AZStd::invoke(comp, AZStd::invoke(proj, *it), AZStd::invoke(proj, *result)))
{
result = it;
}
}
return result;
}
};
}
inline namespace customization_point_object
{
constexpr Internal::min_element_fn min_element{};
}
namespace Internal
{
struct max_element_fn
{
template<class I, class S, class Proj = identity, class Comp = ranges::less>
constexpr auto operator()(I first, S last, Comp comp = {}, Proj proj = {}) const
-> enable_if_t<conjunction_v<
bool_constant<forward_iterator<I>>,
bool_constant<sentinel_for<S, I>>,
bool_constant<indirect_strict_weak_order<Comp, projected<I, Proj>>>
>, I>
{
I result{ first };
for (; first != last; ++first)
{
if (AZStd::invoke(comp, AZStd::invoke(proj, *result), AZStd::invoke(proj, *first)))
{
result = first;
}
}
return result;
}
template<class R, class Proj = identity, class Comp = ranges::less>
constexpr auto operator()(R&& r, Comp comp = {}, Proj proj = {}) const
->enable_if_t<conjunction_v<
bool_constant<forward_range<R>>,
bool_constant<indirect_strict_weak_order<Comp, projected<iterator_t<R>, Proj>>>
>, borrowed_iterator_t<R>>
{
auto first = ranges::begin(r);
auto last = ranges::end(r);
borrowed_iterator_t<R> result{ first };
for (; first != last; ++first)
{
if (AZStd::invoke(comp, AZStd::invoke(proj, *result), AZStd::invoke(proj, *first)))
{
result = first;
}
}
return result;
}
};
}
inline namespace customization_point_object
{
constexpr Internal::max_element_fn max_element{};
}
namespace Internal
{
// C++ Standard footnote
// minmax_element returns the rightmost iterator with the largest value
// and is intentionally different from max_element which returns
// the leftmost iterator with the largest value
// https://eel.is/c++draft/algorithms#footnoteref-225
struct minmax_element_fn
{
template<
class I,
class S,
class Proj = identity,
class Comp = ranges::less>
constexpr auto operator()(I first, S last, Comp comp = {}, Proj proj = {}) const
->enable_if_t<conjunction_v<
bool_constant<forward_iterator<I>>,
bool_constant<sentinel_for<S, I>>,
bool_constant<indirect_strict_weak_order<Comp, projected<I, Proj>>>
>, minmax_element_result<I>>
{
minmax_element_result<I> result{ first, first };
for (; first != last; ++first)
{
// Algorithm requires at most (3/2 * ranges::distance(r)) comparisons
if (auto prevIt = first++; first == last)
{
// Find the leftmost smallest element
if (AZStd::invoke(comp, AZStd::invoke(proj, *prevIt), AZStd::invoke(proj, *result.min)))
{
result.min = prevIt;
}
// Find the rightmost largest element
else if (!AZStd::invoke(comp, AZStd::invoke(proj, *prevIt), AZStd::invoke(proj, *result.max)))
{
result.max = prevIt;
}
break;
}
else
{
// For every two elements performs a transitive comparisons to calculate either new
// leftmost min or rightmost max using at most three comparisons
// (*first < *prevIt) && (*first < result.min), then *first = leftmost min
// (*first < *prevIt) && (*prevIt >= result.max), then *prevIt = rightmost max
// else
// (*first >= *prevIt) && (*prevIt < result.min), then *prevIt = leftmost min
// (*first >= *prevIt) && (*first >= result.max), then *first = rightmost max
if (AZStd::invoke(comp, AZStd::invoke(proj, *first), AZStd::invoke(proj, *prevIt)))
{
if (AZStd::invoke(comp, AZStd::invoke(proj, *first), AZStd::invoke(proj, *result.min)))
{
result.min = first;
}
if (!AZStd::invoke(comp, AZStd::invoke(proj, *prevIt), AZStd::invoke(proj, *result.max)))
{
result.max = prevIt;
}
}
else
{
if (AZStd::invoke(comp, AZStd::invoke(proj, *prevIt), AZStd::invoke(proj, *result.min)))
{
result.min = prevIt;
}
if (!AZStd::invoke(comp, AZStd::invoke(proj, *first), AZStd::invoke(proj, *result.max)))
{
result.max = first;
}
}
}
}
return result;
}
template<class R, class Proj = identity, class Comp = ranges::less>
constexpr auto operator()(R&& r, Comp comp = {}, Proj proj = {}) const
->enable_if_t<conjunction_v<
bool_constant<forward_range<R>>,
bool_constant<indirect_strict_weak_order<Comp, projected<iterator_t<R>, Proj>>>
>, minmax_element_result<borrowed_iterator_t<R>>>
{
auto first = ranges::begin(r);
minmax_element_result<borrowed_iterator_t<R>> result{ first, first };
auto last = ranges::end(r);
for (; first != last; ++first)
{
// Algorithm requires at most (3/2 * ranges::distance(r)) comparisons
if (auto prevIt = first++; first == last)
{
// Find the leftmost smallest element
if (AZStd::invoke(comp, AZStd::invoke(proj, *prevIt), AZStd::invoke(proj, *result.min)))
{
result.min = prevIt;
}
// Find the rightmost largest element
else if (!AZStd::invoke(comp, AZStd::invoke(proj, *prevIt), AZStd::invoke(proj, *result.max)))
{
result.max = prevIt;
}
break;
}
else
{
// For every two elements performs a transitive comparisons to calculate either new
// leftmost min or rightmost max using at most three comparisons
// (*first < *prevIt) && (*first < result.min), then *first = leftmost min
// (*first < *prevIt) && (*prevIt >= result.max), then *prevIt = rightmost max
// else
// (*first >= *prevIt) && (*prevIt < result.min), then *prevIt = leftmost min
// (*first >= *prevIt) && (*first >= result.max), then *first = rightmost max
if (AZStd::invoke(comp, AZStd::invoke(proj, *first), AZStd::invoke(proj, *prevIt)))
{
if (AZStd::invoke(comp, AZStd::invoke(proj, *first), AZStd::invoke(proj, *result.min)))
{
result.min = first;
}
if (!AZStd::invoke(comp, AZStd::invoke(proj, *prevIt), AZStd::invoke(proj, *result.max)))
{
result.max = prevIt;
}
}
else
{
if (AZStd::invoke(comp, AZStd::invoke(proj, *prevIt), AZStd::invoke(proj, *result.min)))
{
result.min = prevIt;
}
if (!AZStd::invoke(comp, AZStd::invoke(proj, *first), AZStd::invoke(proj, *result.max)))
{
result.max = first;
}
}
}
}
return result;
}
};
}
inline namespace customization_point_object
{
constexpr Internal::minmax_element_fn minmax_element{};
}
// find algorithms
namespace Internal
{
struct find_fn
{
template<class I, class S, class T, class Proj = identity, class = enable_if_t<conjunction_v<
bool_constant<input_iterator<I>>,
bool_constant<sentinel_for<S, I>>,
bool_constant<indirect_binary_predicate<ranges::equal_to, projected<I, Proj>, const T*>>
>>>
constexpr I operator()(I first, S last, const T& value, Proj proj = {}) const
{
for (; first != last; ++first)
{
if (AZStd::invoke(proj, *first) == value)
{
return first;
}
}
return first;
}
template<class R, class T, class Proj = identity, class = enable_if_t<conjunction_v<
bool_constant<input_range<R>>,
bool_constant<indirect_binary_predicate<equal_to, projected<iterator_t<R>, Proj>, const T*>>
>>>
constexpr borrowed_iterator_t<R> operator()(R&& r, const T& value, Proj proj = {}) const
{
return operator()(ranges::begin(r), ranges::end(r),
value, AZStd::move(proj));
}
};
}
inline namespace customization_point_object
{
constexpr Internal::find_fn find{};
}
namespace Internal
{
struct find_if_fn
{
template<class I, class S, class Proj = identity, class Pred, class = enable_if_t<conjunction_v<
bool_constant<input_iterator<I>>,
bool_constant<sentinel_for<S, I>>,
bool_constant<indirect_unary_predicate<Pred, projected<I, Proj>>>
>>>
constexpr I operator()(I first, S last, Pred pred, Proj proj = {}) const
{
for (; first != last; ++first)
{
if (AZStd::invoke(pred, AZStd::invoke(proj, *first)))
{
return first;
}
}
return first;
}
template<class R, class Proj = identity, class Pred, class = enable_if_t<conjunction_v<
bool_constant<input_range<R>>,
bool_constant<indirect_unary_predicate<Pred, projected<iterator_t<R>, Proj>>>
>>>
constexpr borrowed_iterator_t<R> operator()(R&& r, Pred pred, Proj proj = {}) const
{
return operator()(ranges::begin(r), ranges::end(r),
AZStd::move(pred), AZStd::move(proj));
}
};
}
inline namespace customization_point_object
{
constexpr Internal::find_if_fn find_if{};
}
namespace Internal
{
struct find_if_not_fn
{
template<class I, class S, class Proj = identity, class Pred, class = enable_if_t<conjunction_v<
bool_constant<input_iterator<I>>,
bool_constant<sentinel_for<S, I>>,
bool_constant<indirect_unary_predicate<Pred, projected<I, Proj>>>
>>>
constexpr I operator()(I first, S last, Pred pred, Proj proj = {}) const
{
for (; first != last; ++first)
{
if (!AZStd::invoke(pred, AZStd::invoke(proj, *first)))
{
return first;
}
}
return first;
}
template<class R, class Proj = identity, class Pred, class = enable_if_t<conjunction_v<
bool_constant<input_range<R>>,
bool_constant<indirect_unary_predicate<Pred, projected<iterator_t<R>, Proj>>>
>>>
constexpr borrowed_iterator_t<R>
operator()(R&& r, Pred pred, Proj proj = {}) const
{
return operator()(ranges::begin(r), ranges::end(r),
AZStd::move(pred), AZStd::move(proj));
}
};
}
inline namespace customization_point_object
{
constexpr Internal::find_if_not_fn find_if_not{};
}
namespace Internal
{
struct find_first_of_fn
{
template<class I1, class S1, class I2, class S2, class Pred = equal_to, class Proj1 = identity, class Proj2 = identity,
class = enable_if_t<conjunction_v<
bool_constant<input_iterator<I1>>,
bool_constant<sentinel_for<S1, I1>>,
bool_constant<forward_iterator<I2>>,
bool_constant<sentinel_for<S2, I2>>,
bool_constant<indirectly_comparable<I1, I2, Pred, Proj1, Proj2>>
>>>
constexpr I1 operator()(I1 first1, S1 last1, I2 first2, S2 last2,
Pred pred = {},
Proj1 proj1 = {}, Proj2 proj2 = {}) const
{
for (; first1 != last1; ++first1)
{
for (I2 elementIt = first2; elementIt != last2; ++elementIt)
{
if (AZStd::invoke(pred, AZStd::invoke(proj1, *first1), AZStd::invoke(proj2, *elementIt)))
{
return first1;
}
}
}
return first1;
}
template<class R1, class R2,class Pred = equal_to, class Proj1 = identity, class Proj2 = identity,
class = enable_if_t<conjunction_v<
bool_constant<input_range<R1>>,
bool_constant<forward_range<R2>>,
bool_constant<indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Pred, Proj1, Proj2>>
>>>
constexpr borrowed_iterator_t<R1> operator()(R1&& r1, R2&& r2,
Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const
{
return operator()(ranges::begin(r1), ranges::end(r1),
ranges::begin(r2), ranges::end(r2),
AZStd::move(pred), AZStd::move(proj1), AZStd::move(proj2));
}
};
}
inline namespace customization_point_object
{
constexpr Internal::find_first_of_fn find_first_of{};
}
// ranges::mismatch
template<class I1, class I2>
using mismatch_result = in_in_result<I1, I2>;
namespace Internal
{
struct mismatch_fn
{
template<class I1, class S1, class I2, class S2, class Pred = equal_to, class Proj1 = identity, class Proj2 = identity,
class = enable_if_t<conjunction_v<
bool_constant<input_iterator<I1>>,
bool_constant<sentinel_for<S1, I1>>,
bool_constant<input_iterator<I2>>,
bool_constant<sentinel_for<S2, I2>>,
bool_constant<indirectly_comparable<I1, I2, Pred, Proj1, Proj2>>
>>>
constexpr mismatch_result<I1, I2> operator()(I1 first1, S1 last1, I2 first2, S2 last2,
Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const
{
for (; first1 != last1 && first2 != last2; ++first1, ++first2)
{
if (!AZStd::invoke(pred, AZStd::invoke(proj1, *first1), AZStd::invoke(proj2, *first2)))
{
return { first1, first2 };
}
}
return { first1, first2 };
}
template<class R1, class R2, class Pred = equal_to, class Proj1 = identity, class Proj2 = identity,
class = enable_if_t<conjunction_v<
bool_constant<input_range<R1>>,
bool_constant<input_range<R2>>,
bool_constant<indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Pred, Proj1, Proj2>>
>>>
constexpr mismatch_result<borrowed_iterator_t<R1>, borrowed_iterator_t<R2>> operator()(R1&& r1, R2&& r2,
Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const
{
return operator()(ranges::begin(r1), ranges::end(r1),
ranges::begin(r2), ranges::end(r2),
AZStd::move(pred), AZStd::move(proj1), AZStd::move(proj2));
}
};
}
inline namespace customization_point_object
{
constexpr Internal::mismatch_fn mismatch{};
}
namespace Internal
{
struct equal_fn
{
template<class I1, class S1, class I2, class S2, class Pred = equal_to, class Proj1 = identity, class Proj2 = identity,
class = enable_if_t<conjunction_v<
bool_constant<input_iterator<I1>>,
bool_constant<sentinel_for<S1, I1>>,
bool_constant<input_iterator<I2>>,
bool_constant<sentinel_for<S2, I2>>,
bool_constant<indirectly_comparable<I1, I2, Pred, Proj1, Proj2>>
>>>
constexpr bool operator()(I1 first1, S1 last1, I2 first2, S2 last2,
Pred pred = {},
Proj1 proj1 = {}, Proj2 proj2 = {}) const
{
if constexpr (sized_sentinel_for<S1, I1> && sized_sentinel_for<S2, I2>)
{
if (ranges::distance(first1, last1) != ranges::distance(first2, last2))
{
return false;
}
}
for (; first1 != last1 && first2 != last2; ++first1, ++first2)
{
if (!AZStd::invoke(pred, AZStd::invoke(proj1, *first1), AZStd::invoke(proj2, *first2)))
{
return false;
}
}
return first1 == last1 && first2 == last2;
}
template<class R1, class R2, class Pred = equal_to, class Proj1 = identity, class Proj2 = identity,
class = enable_if_t<conjunction_v<
bool_constant<input_range<R1>>,
bool_constant<input_range<R2>>,
bool_constant<indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Pred, Proj1, Proj2>>
>>>
constexpr bool operator()(R1&& r1, R2&& r2, Pred pred = {},
Proj1 proj1 = {}, Proj2 proj2 = {}) const
{
return operator()(ranges::begin(r1), ranges::end(r1),
ranges::begin(r2), ranges::end(r2),
AZStd::move(pred), AZStd::move(proj1), AZStd::move(proj2));
}
};
}
inline namespace customization_point_object
{
constexpr Internal::equal_fn equal{};
}
namespace Internal
{
struct search_fn
{
template<class I1, class S1, class I2, class S2, class Pred = equal_to, class Proj1 = identity, class Proj2 = identity,
class = enable_if_t<conjunction_v<
bool_constant<forward_iterator<I1>>,
bool_constant<sentinel_for<S1, I1>>,
bool_constant<forward_iterator<I2>>,
bool_constant<sentinel_for<S2, I2>>,
bool_constant<indirectly_comparable<I1, I2, Pred, Proj1, Proj2>>
>>>
constexpr subrange<I1> operator()(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {},
Proj1 proj1 = {}, Proj2 proj2 = {}) const
{
do
{
I1 it1 = first1;
I2 it2 = first2;
for (;; ++it1, ++it2)
{
if (it2 == last2)
{
// Reached the end of the second iteator sequence
// Therefore the search has succeeded. return the matching range from the first sequence
return { first1, it1 };
}
if (it1 == last1)
{
// The search has failed to find the second iterator sequence within the first
return { last1, last1 };
}
if (!AZStd::invoke(pred, AZStd::invoke(proj1, *it1), AZStd::invoke(proj2, *it2)))
{
// Mismatch found break out of iteration of loop
break;
}
}
// Increment to the next element in the range of [first1, last1) and restart the search
++first1;
} while (true);
}
template<class R1, class R2, class Pred = equal_to, class Proj1 = identity, class Proj2 = identity,
class = enable_if_t<conjunction_v<
bool_constant<forward_range<R1>>,
bool_constant<forward_range<R2>>,
bool_constant<indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Pred, Proj1, Proj2>>
>>>
constexpr borrowed_subrange_t<R1>
operator()(R1&& r1, R2&& r2, Pred pred = {},
Proj1 proj1 = {}, Proj2 proj2 = {}) const
{
return operator()(ranges::begin(r1), ranges::end(r1),
ranges::begin(r2), ranges::end(r2),
AZStd::move(pred), AZStd::move(proj1), AZStd::move(proj2));
}
};
}
inline namespace customization_point_object
{
constexpr Internal::search_fn search{};
}
namespace Internal
{
struct search_n_fn
{
template<class I, class S, class T, class Pred = equal_to, class Proj = identity,
class = enable_if_t<conjunction_v<
bool_constant<forward_iterator<I>>,
bool_constant<sentinel_for<S, I>>,
bool_constant<indirectly_comparable<I, const T*, Pred, Proj>>
>>>
constexpr subrange<I> operator()(I first, S last, iter_difference_t<I> count,
const T& value, Pred pred = {}, Proj proj = {}) const
{
for (; first != last; ++first)
{
iter_difference_t<I> foundCount{};
I searchFirst = first;
for (; foundCount != count && first != last; ++first, ++foundCount)
{
if (!AZStd::invoke(pred, AZStd::invoke(proj, *first), value))
{
break;
}
}
if (foundCount == count)
{
// count consecutive elements matching value have been found
return { searchFirst, first };
}
if (first == last)
{
// search has failed to find count matching elements over the range.
break;
}
}
return { last, last };
}
template<class R, class T, class Pred = equal_to, class Proj = identity,
class = enable_if_t<conjunction_v<
bool_constant<forward_range<R>>,
bool_constant<indirectly_comparable<iterator_t<R>, const T*, Pred, Proj>>
>>>
constexpr borrowed_subrange_t<R> operator()(R&& r, range_difference_t<R> count,
const T& value, Pred pred = {}, Proj proj = {}) const
{
return operator()(ranges::begin(r), ranges::end(r),
AZStd::move(count), value, AZStd::move(pred), AZStd::move(proj));
}
};
}
inline namespace customization_point_object
{
constexpr Internal::search_n_fn search_n{};
}
// ranges::find_end_fn
// use ranges::search
namespace Internal
{
struct find_end_fn
{
template<class I1, class S1, class I2, class S2, class Pred = equal_to, class Proj1 = identity, class Proj2 = identity,
class = enable_if_t<conjunction_v<
bool_constant<forward_iterator<I1>>,
bool_constant<sentinel_for<S1, I1>>,
bool_constant<forward_iterator<I2>>,
bool_constant<sentinel_for<S2, I2>>,
bool_constant<indirectly_comparable<I1, I2, Pred, Proj1, Proj2>>
>>>
constexpr subrange<I1> operator()(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {},
Proj1 proj1 = {}, Proj2 proj2 = {}) const
{
if (first2 == last2)
{
return { last1, last1 };
}
auto foundSubrange = ranges::search(first1, last1, first2, last2, pred, proj1, proj2);
if (foundSubrange.empty())
{
return foundSubrange;
}
do
{
auto nextIt = ranges::next(foundSubrange.begin());
auto nextSubrange = ranges::search(nextIt, last1, first2, last2, pred, proj1, proj2);
if (nextSubrange.empty())
{
return foundSubrange;
}
foundSubrange = AZStd::move(nextSubrange);
} while (true);
}
template<class R1, class R2, class Pred = equal_to, class Proj1 = identity, class Proj2 = identity,
class = enable_if_t<conjunction_v<
bool_constant<forward_range<R1>>,
bool_constant<forward_range<R2>>,
bool_constant<indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Pred, Proj1, Proj2>>
>>>
constexpr borrowed_subrange_t<R1> operator()(R1&& r1, R2&& r2, Pred pred = {},
Proj1 proj1 = {}, Proj2 proj2 = {}) const
{
return operator()(ranges::begin(r1), ranges::end(r1),
ranges::begin(r2), ranges::end(r2),
AZStd::move(pred), AZStd::move(proj1), AZStd::move(proj2));
}
};
}
inline namespace customization_point_object
{
constexpr Internal::find_end_fn find_end{};
}
} // namespace AZStd::ranges

@ -0,0 +1,121 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/std/function/identity.h>
#include <AzCore/std/ranges/ranges.h>
namespace AZStd::ranges
{
struct equal_to
{
template<class T, class U>
constexpr auto operator()(T&& t, U&& u) const ->
enable_if_t<equality_comparable_with<T, U>, decltype(AZStd::forward<T>(t) == AZStd::forward<U>(u))>
{
return AZStd::forward<T>(t) == AZStd::forward<U>(u);
}
using is_transparent = void;
};
struct not_equal_to
{
template<class T, class U>
constexpr auto operator()(T&& t, U&& u) const ->
enable_if_t<equality_comparable_with<T, U>, decltype(!ranges::equal_to{}(AZStd::forward<T>(t), AZStd::forward<U>(u)))>
{
return !ranges::equal_to{}(AZStd::forward<T>(t), AZStd::forward<U>(u));
}
using is_transparent = void;
};
struct less
{
template<class T, class U>
constexpr auto operator()(T&& t, U&& u) const ->
enable_if_t<totally_ordered_with<T, U>, decltype(AZStd::forward<T>(t) < AZStd::forward<U>(u))>
{
return AZStd::forward<T>(t) < AZStd::forward<U>(u);
}
using is_transparent = void;
};
struct greater
{
template<class T, class U>
constexpr auto operator()(T&& t, U&& u) const ->
enable_if_t<totally_ordered_with<T, U>, decltype(ranges::less{}(AZStd::forward<T>(t) < AZStd::forward<U>(u)))>
{
return ranges::less{}(AZStd::forward<U>(u) < AZStd::forward<T>(t));
}
using is_transparent = void;
};
struct greater_equal
{
template<class T, class U>
constexpr auto operator()(T&& t, U&& u) const ->
enable_if_t<totally_ordered_with<T, U>, decltype(!ranges::less{}(AZStd::forward<T>(t), AZStd::forward<U>(u)))>
{
return !ranges::less{}(AZStd::forward<T>(t), AZStd::forward<U>(u));
}
using is_transparent = void;
};
struct less_equal
{
template<class T, class U>
constexpr auto operator()(T&& t, U&& u) const ->
enable_if_t<totally_ordered_with<T, U>, decltype(!ranges::less{}(AZStd::forward<U>(u), AZStd::forward<T>(t)))>
{
return !ranges::less{}(AZStd::forward<U>(u), AZStd::forward<T>(t));
}
using is_transparent = void;
};
} // namespace AZStd::ranges
// Iterator Common algorithm requirement concepts
// https://eel.is/c++draft/alg.req
namespace AZStd
{
template<class I1, class I2, class R, class P1 = identity, class P2 = identity, class = void>
/*concept*/ constexpr bool indirectly_comparable = false;
template<class I1, class I2, class R, class P1, class P2>
/*concept*/ constexpr bool indirectly_comparable<I1, I2, R, P1, P2, enable_if_t<
indirect_binary_predicate<R, projected<I1, P1>, projected<I2, P2>>>> = true;
template<class I, class = void>
/*concept*/ constexpr bool permutable = false;
template<class I>
/*concept*/ constexpr bool permutable<I, enable_if_t<conjunction_v<
bool_constant<forward_iterator<I>>,
bool_constant<indirectly_movable_storable<I, I>>,
bool_constant<indirectly_swappable<I, I>> >>> = true;
template<class I1, class I2, class Out, class R = ranges::less, class P1 = identity, class P2 = identity, class = void>
/*concept*/ constexpr bool mergeable = false;
template<class I1, class I2, class Out, class R, class P1, class P2>
/*concept*/ constexpr bool mergeable<I1, I2, Out, R, P1, P2, enable_if_t<conjunction_v<
bool_constant<input_iterator<I1>>,
bool_constant<input_iterator<I2>>,
bool_constant<weakly_incrementable<Out>>,
bool_constant<indirectly_copyable<I1, Out>>,
bool_constant<indirectly_copyable<I2, Out>>,
bool_constant<indirect_strict_weak_order<R, projected<I1, P1>, projected<I2, P2>>> >>> = true;
template<class I, class R = ranges::less, class P = identity, class = void>
/*concept*/ constexpr bool sortable = false;
template<class I, class R, class P>
/*concept*/ constexpr bool sortable<I, R, P, enable_if_t<conjunction_v<
bool_constant<permutable<I>>,
bool_constant<indirect_strict_weak_order<R, projected<I, P>>> >>> = true;
}

@ -0,0 +1,77 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/std/ranges/ranges.h>
#include <AzCore/std/optional.h>
namespace AZStd::ranges
{
template<class R, class = void>
class ref_view;
template<class R>
class ref_view<R, enable_if_t<ranges::range<R> && is_object_v<R>>>
: public ranges::view_interface<ref_view<R>>
{
private:
static void bindable_to_range(R&);
static void bindable_to_range(R&&) = delete;
public:
template<class T, class = enable_if_t<conjunction_v<
bool_constant<Internal::different_from<T, ref_view>>,
bool_constant<convertible_to<T, R&>>,
Internal::sfinae_trigger<decltype(bindable_to_range(declval<T>()))>
>>>
constexpr ref_view(T&& t)
: m_range{ addressof(static_cast<R&>(AZStd::forward<T>(t))) }
{}
constexpr R& base() const
{
return *m_range;
}
constexpr iterator_t<R> begin() const
{
return ranges::begin(*m_range);
}
constexpr sentinel_t<R> end() const
{
return ranges::end(*m_range);
}
template<class Rn = R>
constexpr auto empty() const -> enable_if_t<Internal::sfinae_trigger_v<decltype(ranges::empty(*declval<Rn*>()))>, bool>
{
return ranges::empty(*m_range);
}
template<class Rn = R>
constexpr auto size() const -> enable_if_t<sized_range<R>, decltype(ranges::size(*declval<Rn*>()))>
{
return ranges::size(*m_range);
}
template<class Rn = R>
constexpr auto data() const -> enable_if_t<contiguous_range<R>, decltype(ranges::data(*declval<Rn*>()))>
{
return ranges::data(*m_range);
}
private:
R* m_range{};
};
//! deduction guides
template<class R>
ref_view(R&) -> ref_view<R>;
template<class T>
inline constexpr bool enable_borrowed_range<ref_view<T>> = true;
}

@ -0,0 +1,89 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/std/ranges/ranges_adaptor.h>
namespace AZStd::ranges
{
template<class T, class = void>
class single_view;
namespace views
{
namespace Internal
{
struct single_view_fn
{
template <class View>
constexpr decltype(auto) operator()(View&& view) const
{
return single_view<decay_t<View>>(AZStd::forward<View>(view));
}
};
}
inline namespace customization_point_object
{
constexpr Internal::single_view_fn single{};
}
}
template<class T>
class single_view<T, enable_if_t<copy_constructible<T>&& is_object_v<T>>>
: public view_interface<single_view<T>>
{
public:
template<class T2 = T, class = enable_if_t<default_initializable<T2>>>
single_view() {}
constexpr explicit single_view(const T& t)
: m_value(in_place, t)
{}
constexpr explicit single_view(T&& t)
: m_value(in_place, AZStd::move(t))
{}
template<class... Args, enable_if_t<constructible_from<T, Args...>>* = nullptr>
constexpr explicit single_view(in_place_t, Args&&... args)
: m_value{ in_place, AZStd::forward<Args>(args)... }
{}
constexpr T* begin() noexcept
{
return data();
}
constexpr const T* begin() const noexcept
{
return data();
}
constexpr T* end() noexcept
{
return data() + 1;
}
constexpr const T* end() const noexcept
{
return data() + 1;
}
static constexpr size_t size() noexcept
{
return 1;
}
constexpr T* data() noexcept
{
return m_value.operator->();
}
constexpr const T* data() const noexcept
{
return m_value.operator->();
}
private:
Internal::copyable_box<T> m_value;
};
template<class T>
single_view(T) -> single_view<T>;
}

@ -0,0 +1,235 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/std/ranges/all_view.h>
#include <AzCore/std/ranges/ranges_adaptor.h>
#include <AzCore/std/ranges/ranges_algorithm.h>
#include <AzCore/std/ranges/ranges_functional.h>
#include <AzCore/std/ranges/single_view.h>
namespace AZStd::ranges
{
template<class View, class Pattern, class = enable_if_t<conjunction_v<
bool_constant<forward_range<View>>,
bool_constant<forward_range<Pattern>>,
bool_constant<view<View>>,
bool_constant<view<Pattern>>,
bool_constant<indirectly_comparable<iterator_t<View>, iterator_t<Pattern>, ranges::equal_to>>
>>>
class split_view;
// views::split customization point
namespace views
{
namespace Internal
{
struct split_view_fn
: Internal::range_adaptor_closure<split_view_fn>
{
template <class View, class Pattern, class = enable_if_t<conjunction_v<
bool_constant<viewable_range<View>>
>>>
constexpr auto operator()(View&& view, Pattern&& pattern) const
{
return split_view(AZStd::forward<View>(view), AZStd::forward<Pattern>(pattern));
}
};
}
inline namespace customization_point_object
{
constexpr Internal::split_view_fn split{};
}
}
template<class View, class Pattern, class>
class split_view
: public view_interface<split_view<View, Pattern>>
{
struct iterator;
struct sentinel;
public:
template <bool Enable = default_initializable<View> && default_initializable<Pattern>,
class = enable_if_t<Enable>>
split_view() {}
constexpr split_view(View base, Pattern pattern)
: m_base(AZStd::move(base))
, m_pattern(AZStd::move(pattern))
{}
template<class R, class = enable_if_t<conjunction_v<
bool_constant<forward_range<R>>,
bool_constant<constructible_from<View, views::all_t<R>>>,
bool_constant<constructible_from<Pattern, single_view<range_value_t<R>>>>
>>>
constexpr split_view(R&& r, range_value_t<R> e)
: m_base{ views::all(AZStd::forward<R>(r)) }
, m_pattern{ views::single(AZStd::move(e)) }
{
}
template <bool Enable = copy_constructible<View>, class = enable_if_t<Enable>>
constexpr View base() const&
{
return m_base;
}
constexpr View base()&&
{
return AZStd::move(m_base);
}
constexpr iterator begin()
{
return { *this, ranges::begin(m_base), find_next(ranges::begin(m_base)) };
}
constexpr auto end()
{
if constexpr (common_range<View>)
{
return iterator{ *this, ranges::end(m_base), {} };
}
else
{
return sentinel{ *this };
}
}
constexpr subrange<iterator_t<View>> find_next(iterator_t<View> it)
{
auto [first, last] = ranges::search(subrange(it, ranges::end(m_base)), m_pattern);
if (first != ranges::end(m_base) && ranges::empty(m_pattern))
{
++first;
++last;
}
return { first, last };
}
private:
View m_base;
Pattern m_pattern;
};
template<class R, class P>
split_view(R&&, P&&)->split_view<views::all_t<R>, views::all_t<P>>;
template<class R, class = enable_if_t<forward_range<R>>>
split_view(R&&, range_value_t<R>)
-> split_view<views::all_t<R>, single_view<range_value_t<R>>>;
template<class View, class Pattern, class Enable>
struct split_view<View, Pattern, Enable>::iterator
{
using iterator_concept = forward_iterator_tag;
using iterator_category = input_iterator_tag;
using value_type = subrange<iterator_t<View>>;
using difference_type = range_difference_t<View>;
iterator() = default;
constexpr iterator(split_view& parent, iterator_t<View> current, subrange<iterator_t<View>> patternSubrange)
: m_parent(&parent)
, m_current(AZStd::move(current))
, m_next(AZStd::move(patternSubrange))
{
}
constexpr iterator_t<View> base() const
{
return m_current;
}
constexpr value_type operator*() const
{
return { m_current, m_next.begin() };
}
constexpr iterator& operator++()
{
m_current = m_next.begin();
if (m_current != ranges::end(m_parent->m_base))
{
m_current = m_next.end();
if (m_current == ranges::end(m_parent->m_base))
{
m_trailing_empty = true;
m_next = { m_current, m_current };
}
else
{
m_next = m_parent->find_next(m_current);
}
}
else
{
m_trailing_empty = false;
}
return *this;
}
constexpr iterator operator++(int)
{
auto tmp = *this;
++(*this);
return tmp;
}
friend constexpr bool operator==(const iterator& x, const iterator& y)
{
return x.m_current == y.m_current && x.m_trailing_empty == y.m_trailing_empty;
}
friend constexpr bool operator!=(const iterator& y, const iterator& x)
{
return !operator==(x, y);
}
private:
//! reference to parent split_view
split_view<View, Pattern>* m_parent{};
//! iterator of the current split content of the view
iterator_t<View> m_current{};
//! The next subrange within the view that matches the pattern
subrange<iterator_t<View>> m_next{};
//! Set to true to indicate an iterator
//! pointing to the empty after the last pattern if the pattern is at the end of the view
//! For a View="a,b,c," and Pattern=",", the last iterator will point to the empty element
//! after the last comma. This iteator will not match the sentinel iterator to allow users
//! to know between the end of the View and an empty element after the last pattern
bool m_trailing_empty{};
};
template<class View, class Pattern, class Enable>
struct split_view<View, Pattern, Enable>::sentinel
{
sentinel() = default;
explicit constexpr sentinel(split_view& parent)
: m_end{ ranges::end(parent.m_base) }
{}
friend constexpr bool operator==(const iterator& x, const sentinel& y)
{
return x.m_current == y.m_end && !x.m_trailing_empty;
}
friend constexpr bool operator==(const sentinel& y, const iterator& x)
{
return operator==(x, y);
}
friend constexpr bool operator!=(const iterator& x, const sentinel& y)
{
return !operator==(x, y);
}
friend constexpr bool operator!=(const sentinel& y, const iterator& x)
{
return !operator==(x, y);
}
private:
sentinel_t<View> m_end;
};
}

@ -0,0 +1,290 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/std/ranges/ranges_adaptor.h>
#include <AzCore/std/tuple.h>
// Specializing tuple in std:: namespace since tuple_size and tuple_element structs
// are alias templates inside of the AZStd:: namespace
namespace std
{
AZ_PUSH_DISABLE_WARNING(, "-Wmismatched-tags")
template<class I, class S, AZStd::ranges::subrange_kind K>
struct tuple_size<AZStd::ranges::subrange<I, S, K>>
: integral_constant<size_t, 2> {};
template<class I, class S, AZStd::ranges::subrange_kind K>
struct tuple_element<0, AZStd::ranges::subrange<I, S, K>>
{
using type = I;
};
template<class I, class S, AZStd::ranges::subrange_kind K>
struct tuple_element<1, AZStd::ranges::subrange<I, S, K>>
{
using type = S;
};
template<class I, class S, AZStd::ranges::subrange_kind K>
struct tuple_element<0, const AZStd::ranges::subrange<I, S, K>>
{
using type = I;
};
template<class I, class S, AZStd::ranges::subrange_kind K>
struct tuple_element<1, const AZStd::ranges::subrange<I, S, K>>
{
using type = S;
};
AZ_POP_DISABLE_WARNING
}
namespace AZStd::ranges
{
namespace Internal
{
template <typename From, typename To>
/*concept*/ constexpr bool uses_nonqualification_pointer_conversion =
is_pointer_v<From> && is_pointer_v<To> &&
!convertible_to<remove_pointer_t<From>(*)[], remove_pointer_t<To>(*)[]>;
template<class From, class To>
/*concept*/ constexpr bool convertible_to_non_slicing =
convertible_to<From, To> &&
!uses_nonqualification_pointer_conversion<decay_t<From>, decay_t<To>>;
template<class T, class = void>
/*concept*/ constexpr bool pair_like = false;
template<class T>
/*concept*/ constexpr bool pair_like<T, enable_if_t<conjunction_v<
bool_constant<!is_reference_v<T>>,
sfinae_trigger<typename tuple_size<T>::type>,
bool_constant<derived_from<tuple_size<T>, integral_constant<size_t, 2>>>,
sfinae_trigger<
tuple_element_t<0, remove_const_t<T>>,
tuple_element_t<1, remove_const_t<T>>>,
bool_constant<convertible_to<decltype(AZStd::get<0>(declval<T>())), const tuple_element_t<0, T>&>>,
bool_constant<convertible_to<decltype(AZStd::get<1>(declval<T>())), const tuple_element_t<1, T>&>>>
>> = true;
template<class T, class U, class V, class = void>
/*concept*/ constexpr bool pair_like_convertible_from = false;
template<class T, class U, class V>
/*concept*/ constexpr bool pair_like_convertible_from<T, U, V, enable_if_t<
!range<T> && pair_like<T> && constructible_from<T, U, V>>> =
convertible_to_non_slicing<U, tuple_element_t<0, T>> &&
convertible_to<V, tuple_element_t<1, T>>;
}
template<class I, class S, subrange_kind K>
class subrange<I, S, K, enable_if_t<conjunction_v<
bool_constant<input_or_output_iterator<I>>,
bool_constant<sentinel_for<S, I>>,
bool_constant<(K == subrange_kind::sized || !sized_sentinel_for<S, I>)>>
>>
: public view_interface<subrange<I, S, K>>
{
static constexpr bool StoreSize = K == subrange_kind::sized && !sized_sentinel_for<S, I>;
public:
template<class I2 = I, class = enable_if_t<default_initializable<I2>>>
constexpr subrange() {}
template<class I2, class = enable_if_t<Internal::convertible_to_non_slicing<I2, I> && !StoreSize>>
constexpr subrange(I2 i, S s)
: m_begin(AZStd::move(i))
, m_end(s)
{
}
template<class I2, class = enable_if_t<Internal::convertible_to_non_slicing<I2, I> && K == subrange_kind::sized>>
constexpr subrange(I2 i, S s, make_unsigned_t<iter_difference_t<I>> n)
: m_begin(AZStd::move(i))
, m_end(s)
{
if constexpr (StoreSize)
{
m_size = n;
}
}
template<class R, class = enable_if_t<conjunction_v<
bool_constant<Internal::different_from<R, subrange>>,
bool_constant<borrowed_range<R>>,
bool_constant<Internal::convertible_to_non_slicing<iterator_t<R>, I>>,
bool_constant<convertible_to<sentinel_t<R>, S>>,
bool_constant<(!StoreSize || sized_range<R>)>>
>>
constexpr subrange(R&& r)
: m_begin{ ranges::begin(AZStd::forward<R>(r)) }
, m_end{ ranges::end(AZStd::forward<R>(r)) }
{
if constexpr (StoreSize)
{
m_size = ranges::size(AZStd::forward<R>(r));
}
}
template<class R, class = enable_if_t<conjunction_v<
bool_constant<borrowed_range<R>>,
bool_constant<Internal::convertible_to_non_slicing<iterator_t<R>, I>>,
bool_constant<convertible_to<sentinel_t<R>, S>>,
bool_constant<(K == subrange_kind::sized)>>
>>
constexpr subrange(R&& r, make_unsigned_t<iter_difference_t<I>> n)
: subrange{ ranges::begin(r), ranges::end(r), n }
{
}
template<class PairLike, class = enable_if_t<conjunction_v<
bool_constant<Internal::different_from<PairLike, subrange>>,
bool_constant<Internal::pair_like_convertible_from<PairLike, const I&, const S&>>>
>>
constexpr operator PairLike() const
{
return PairLike{ m_begin, m_end };
}
template<bool Enable = copyable<I>, class = enable_if_t<Enable>>
constexpr I begin() const
{
return m_begin;
}
template<bool Enable = !copyable<I>, class = enable_if_t<Enable>>
[[nodiscard]] constexpr I begin()
{
return AZStd::move(m_begin);
}
constexpr S end() const
{
return m_end;
}
constexpr bool empty() const
{
return m_begin == m_end;
}
template<bool Enable = (K == subrange_kind::sized), class = enable_if_t<Enable>>
constexpr make_unsigned_t<iter_difference_t<I>> size() const
{
if constexpr (StoreSize)
{
return m_size;
}
else
{
using unsigned_difference_type = make_unsigned_t<iter_difference_t<I>>;
return static_cast<unsigned_difference_type>(m_end - m_begin);
}
}
template<bool Enable = forward_iterator<I>, class = enable_if_t<Enable>>
[[nodiscard]] constexpr subrange next(iter_difference_t<I> n = 1) const&
{
auto tmp = *this;
tmp.advance(n);
return tmp;
}
[[nodiscard]] constexpr subrange next(iter_difference_t<I> n = 1)&&
{
advance(n);
return AZStd::move(*this);
}
template<bool Enable = bidirectional_iterator<I>, class = enable_if_t<Enable>>
[[nodiscard]] constexpr subrange prev(iter_difference_t<I> n = 1) const
{
auto tmp = *this;
tmp.advance(-n);
return tmp;
}
constexpr subrange& advance(iter_difference_t<I> n)
{
using unsigned_difference_type = AZStd::make_unsigned_t<iter_difference_t<I>>;
if constexpr (bidirectional_iterator<I>)
{
if (n < 0)
{
ranges::advance(m_begin, n);
if constexpr (StoreSize)
{
m_size += static_cast<unsigned_difference_type>(-n);
}
return *this;
}
}
auto actualAdvanceDist = n - ranges::advance(m_begin, n, m_end);
if constexpr (StoreSize)
{
m_size -= static_cast<unsigned_difference_type>(actualAdvanceDist);
}
return *this;
}
private:
I m_begin{};
S m_end{};
// Size member will not count against the size of the class when using no_unique_address
struct SizeNotStored
{
constexpr SizeNotStored() noexcept = default;
};
using size_type = AZStd::conditional_t<StoreSize, make_unsigned_t<iter_difference_t<I>>, SizeNotStored>;
AZ_NO_UNIQUE_ADDRESS size_type m_size{};
};
template<class I, class S, class = enable_if_t<input_or_output_iterator<I> && sentinel_for<S, I>>>
subrange(I, S) -> subrange<I, S>;
template<class I, class S, class = enable_if_t<input_or_output_iterator<I>&& sentinel_for<S, I>>>
subrange(I, S, make_unsigned_t<iter_difference_t<I>>) -> subrange<I, S, subrange_kind::sized>;
template<class R, class = enable_if_t<borrowed_range<R>> >
subrange(R&&) -> subrange<iterator_t<R>, sentinel_t<R>,
(sized_range<R> || sized_sentinel_for<sentinel_t<R>, iterator_t<R>>)
? subrange_kind::sized : subrange_kind::unsized>;
template<class R, class = enable_if_t<borrowed_range<R>> >
subrange(R&&, make_unsigned_t<range_difference_t<R>>) ->
subrange<iterator_t<R>, sentinel_t<R>, subrange_kind::sized>;
template<size_t N, class I, class S, subrange_kind K, class = enable_if_t<((N == 0 && copyable<I>) || N == 1)>>
constexpr auto get(const subrange<I, S, K>& r)
{
if constexpr (N == 0)
{
return r.begin();
}
else
{
return r.end();
}
}
template<size_t N, class I, class S, subrange_kind K, class = enable_if_t<(N < 2)>>
constexpr auto get(subrange<I, S, K>&& r)
{
if constexpr (N == 0)
{
return r.begin();
}
else
{
return r.end();
}
}
template<class I, class S, subrange_kind K>
inline constexpr bool enable_borrowed_range<subrange<I, S, K>> = true;
}
namespace AZStd
{
using ranges::get;
}

@ -0,0 +1,116 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/std/base.h>
#include <AzCore/std/concepts/concepts_assignable.h>
#include <AzCore/std/concepts/concepts_constructible.h>
#include <AzCore/std/typetraits/conjunction.h>
#include <AzCore/std/typetraits/disjunction.h>
#include <AzCore/std/typetraits/extent.h>
#include <AzCore/std/typetraits/integral_constant.h>
#include <AzCore/std/typetraits/is_assignable.h>
#include <AzCore/std/typetraits/is_array.h>
#include <AzCore/std/typetraits/is_class.h>
#include <AzCore/std/typetraits/is_enum.h>
#include <AzCore/std/typetraits/is_void.h>
#include <AzCore/std/typetraits/remove_cvref.h>
#include <AzCore/std/typetraits/void_t.h>
#include <AzCore/std/utility/move.h>
#include <AzCore/std/utility/declval.h>
namespace AZStd
{
// Bring std utility functions into AZStd namespace
using std::forward;
}
namespace AZStd::ranges::Internal
{
template <class T, class U, class = void>
constexpr bool is_class_or_enum_with_swap_adl = false;
template <class T, class U>
constexpr bool is_class_or_enum_with_swap_adl<T, U, enable_if_t<conjunction_v<
disjunction<
disjunction<is_class<remove_cvref_t<T>>, is_enum<remove_cvref_t<T>>>,
disjunction<is_class<remove_cvref_t<U>>, is_enum<remove_cvref_t<U>>>>,
is_void<void_t<decltype(swap(declval<T&>(), declval<U&>()))>>
>>> = true;
template <class T>
void swap(T&, T&) = delete;
struct swap_fn
{
template <class T, class U>
constexpr auto operator()(T&& t, U&& u) const noexcept(noexcept(swap(AZStd::forward<T>(t), AZStd::forward<U>(u))))
->enable_if_t<is_class_or_enum_with_swap_adl<T, U>>
{
swap(AZStd::forward<T>(t), AZStd::forward<U>(u));
}
// ranges::swap customization point https://eel.is/c++draft/concepts#concept.swappable-2.2
// Implemented in ranges.h as to prevent circular dependency.
// ranges::swap_ranges depends on the range concepts that can't be defined here
template <class T, class U>
constexpr auto operator()(T&& t, U&& u) const noexcept(noexcept((*this)(*t, *u)))
->enable_if_t<conjunction_v<
bool_constant<!is_class_or_enum_with_swap_adl<T, U>>,
is_array<T>,
is_array<U>,
bool_constant<extent_v<T> == extent_v<U>>
>>;
template <class T>
constexpr auto operator()(T& t1, T& t2) const noexcept(noexcept(is_nothrow_move_constructible_v<T> && is_nothrow_move_assignable_v<T>))
->enable_if_t<conjunction_v<bool_constant<move_constructible<T>>, bool_constant<assignable_from<T&, T>> >>
{
auto temp(AZStd::move(t1));
t1 = AZStd::move(t2);
t2 = AZStd::move(temp);
}
};
}
namespace AZStd::ranges
{
inline namespace customization_point_object
{
inline constexpr auto swap = Internal::swap_fn{};
}
}
namespace AZStd::Internal
{
template <class T, class = void>
constexpr bool swappable_impl = false;
template <class T>
constexpr bool swappable_impl<T, void_t<decltype(AZStd::ranges::swap(declval<T&>(), declval<T&>()))>> = true;
template <class T, class U, class = void>
constexpr bool swappable_with_impl = false;
template <class T, class U>
constexpr bool swappable_with_impl<T, U, enable_if_t<conjunction_v<
bool_constant<common_reference_with<T, U>>,
is_void<void_t<
decltype(AZStd::ranges::swap(declval<T&>(), declval<T&>())),
decltype(AZStd::ranges::swap(declval<U&>(), declval<U&>())),
decltype(AZStd::ranges::swap(declval<T&>(), declval<U&>())),
decltype(AZStd::ranges::swap(declval<U&>(), declval<T&>()))>> >>> = true;
}
namespace AZStd
{
template<class T>
/*concept*/ constexpr bool swappable = Internal::swappable_impl<T>;
template<class T, class U>
/*concept*/ constexpr bool swappable_with = Internal::swappable_with_impl<T, U>;
}

@ -0,0 +1,395 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/std/ranges/all_view.h>
#include <AzCore/std/ranges/empty_view.h>
#include <AzCore/std/ranges/ranges_algorithm.h>
#include <AzCore/std/tuple.h>
namespace AZStd::ranges
{
template<class... Views>
class zip_view;
template<class... Views>
inline constexpr bool enable_borrowed_range<zip_view<Views...>> = (enable_borrowed_range<Views> && ...);
// views::zip customization point
namespace views
{
namespace Internal
{
struct zip_view_fn
{
template <class... Views>
constexpr auto operator()(Views&&... views) const
{
if constexpr (sizeof...(Views) == 0)
{
return views::empty<tuple<>>;
}
else
{
return zip_view<views::all_t<decltype((declval<Views>()))>...>(AZStd::forward<Views>(views)...);
}
}
};
}
inline namespace customization_point_object
{
constexpr Internal::zip_view_fn zip{};
}
}
namespace ZipViewInternal
{
template<class... Rs>
/*concept*/ constexpr bool zip_is_common = (sizeof...(Rs) == 1 && (common_range<Rs> && ...)) ||
(!(bidirectional_range<Rs> && ...) && (common_range<Rs> && ...)) ||
((random_access_range<Rs> && ...) && (sized_range<Rs> && ...));
template<class... Ts>
using tuple_or_pair = tuple<Ts...>;
template<class F, class Tuple>
constexpr auto tuple_transform(F&& f, Tuple&& tuple)
{
auto TransformToResultTuple = [&](auto&&... elements)
{
return tuple_or_pair<invoke_result_t<F&, decltype(elements)>...>(
AZStd::invoke(f, AZStd::forward<decltype(elements)>(elements))...);
};
return AZStd::apply(AZStd::move(TransformToResultTuple), AZStd::forward<Tuple>(tuple));
}
template<class F, class Tuple>
constexpr void tuple_for_each(F&& f, Tuple&& tuple)
{
auto InvokeTupleElement = [&](auto&&... elements)
{
(AZStd::invoke(f, AZStd::forward<decltype(elements)>(elements)), ...);
};
AZStd::apply(AZStd::move(InvokeTupleElement), AZStd::forward<Tuple>(tuple));
}
template<class F, class Tuple1, class Tuple2, size_t... Indices>
constexpr decltype(auto) tuple_zip(F&& f, AZStd::index_sequence<Indices...>,
Tuple1&& tuple1, Tuple2&& tuple2)
{
(AZStd::invoke(AZStd::forward<F>(f), AZStd::get<Indices>(tuple1), AZStd::get<Indices>(tuple2)), ...);
}
}
template<class... Views>
class zip_view
: public enable_if_t<conjunction_v<
bool_constant<(sizeof...(Views) > 0)>,
bool_constant<input_range<Views>>...,
bool_constant<view<Views>>...
>, view_interface<zip_view<Views...>>>
{
// [range.zip.iterator], class template zip_view::iterator
template<bool>
class iterator;
// [range.zip.sentinel], class template zip_view::sentinel
template<bool>
class sentinel; // exposition only
public:
zip_view() = default;
constexpr explicit zip_view(Views... views);
template<bool Enable = !conjunction_v<bool_constant<Internal::simple_view<Views>>...>, class = enable_if_t<Enable>>
constexpr auto begin();
template<bool Enable = conjunction_v<bool_constant<range<const Views>>...>, class = enable_if_t<Enable>>
constexpr auto begin() const;
template<bool Enable = !conjunction_v<bool_constant<Internal::simple_view<Views>>...>, class = enable_if_t<Enable>>
constexpr auto end();
template<bool Enable = conjunction_v<bool_constant<range<const Views>>...>, class = enable_if_t<Enable>>
constexpr auto end() const;
template<bool Enable = conjunction_v<bool_constant<sized_range<Views>>...>, class = enable_if_t<Enable>>
constexpr auto size();
template<bool Enable = conjunction_v<bool_constant<sized_range<const Views>>...>, class = enable_if_t<Enable>>
constexpr auto size() const;
private:
tuple<Views...> m_views;
};
template<class... Rs>
zip_view(Rs&&...)->zip_view<views::all_t<Rs>...>;
namespace ZipViewInternal
{
template<bool Const, class... Views>
/*concept*/ constexpr bool all_random_access = (random_access_range<::AZStd::ranges::Internal::maybe_const<Const, Views>>&&...);
template<bool Const, class... Views>
/*concept*/ constexpr bool all_bidirectional = (bidirectional_range<::AZStd::ranges::Internal::maybe_const<Const, Views>>&&...);
template<bool Const, class... Views>
/*concept*/ constexpr bool all_forward = (forward_range<::AZStd::ranges::Internal::maybe_const<Const, Views>>&&...);
struct requirements_fulfilled {};
}
template<class... Views>
template<bool Const>
class zip_view<Views...>::iterator
: public enable_if_t<(conjunction_v<
bool_constant<(sizeof...(Views) > 0)>,
bool_constant<input_range<Views>>...,
bool_constant<view<Views>>...>),
ZipViewInternal::requirements_fulfilled>
{
friend class zip_view<Views...>;
template<bool>
friend class zip_view<Views...>::sentinel;
constexpr explicit iterator(ZipViewInternal::tuple_or_pair<iterator_t<::AZStd::ranges::Internal::maybe_const<Const, Views>>...>);
public:
using iterator_category = input_iterator_tag; // not always present
using iterator_concept = conditional_t<ZipViewInternal::all_random_access<Const, Views...>, random_access_iterator_tag,
conditional_t<ZipViewInternal::all_bidirectional<Const, Views...>, bidirectional_iterator_tag,
conditional_t<ZipViewInternal::all_forward<Const, Views...>, forward_iterator_tag, input_iterator_tag>>>;
using value_type = ZipViewInternal::tuple_or_pair<range_value_t<::AZStd::ranges::Internal::maybe_const<Const, Views>>...>;
using difference_type = common_type_t<range_difference_t<::AZStd::ranges::Internal::maybe_const<Const, Views>>...>;
private:
constexpr auto view_iterator_to_value_tuple(difference_type n) const;
template<size_t... Indices>
static constexpr auto any_iterator_equal(const iterator& x, const iterator& y, AZStd::index_sequence<Indices...>);
template<size_t... Indices>
static constexpr auto min_distance_in_views(const iterator& x, const iterator& y, AZStd::index_sequence<Indices...>);
public:
iterator() = default;
template<bool Enable = Const && conjunction_v<
bool_constant<convertible_to<iterator_t<Views>, iterator_t<::AZStd::ranges::Internal::maybe_const<Const, Views>>>>...>,
class = enable_if_t<Enable>>
constexpr iterator(iterator<!Const> other);
constexpr auto operator*() const;
constexpr iterator& operator++();
constexpr decltype(auto) operator++(int);
template<bool Enable = ZipViewInternal::all_bidirectional<Const, Views...>, class = enable_if_t<Enable>>
constexpr auto operator--()->iterator&;
template<bool Enable = ZipViewInternal::all_bidirectional<Const, Views...>, class = enable_if_t<Enable>>
constexpr auto operator--(int)->iterator;
template<bool Enable = ZipViewInternal::all_random_access<Const, Views...>, class = enable_if_t<Enable>>
constexpr auto operator+=(difference_type x)->iterator&;
template<bool Enable = ZipViewInternal::all_random_access<Const, Views...>, class = enable_if_t<Enable>>
constexpr auto operator-=(difference_type x)->iterator&;
template<bool Enable = ZipViewInternal::all_random_access<Const, Views...>, class = enable_if_t<Enable>>
constexpr auto operator[](difference_type n) const;
// Out-of-line defintions with these friend functions are possible, but quite a mess signature wise
// that is why the defintions are inline, instead of
// template<bool Const, class... Views>
// constexpr auto operator==(const typename zip_views<Views...>::template iterator<Const>& x,
// const typename zip_views<Views...>::template iterator<Const>& y){}
template<bool Enable = conjunction_v<bool_constant<equality_comparable<iterator_t<::AZStd::ranges::Internal::maybe_const<Const, Views>>>>...>,
class = enable_if_t<Enable>>
friend constexpr auto operator==(const iterator& x, const iterator& y) -> bool
{
if constexpr (ZipViewInternal::all_bidirectional<Const, Views...>)
{
return x.m_current == y.m_current;
}
else
{
// Returns true if it at least one of the iterator views are equal
return any_iterator_equal(x, y, AZStd::index_sequence_for<Views...>{});
}
}
template<bool Enable = conjunction_v<bool_constant<equality_comparable<iterator_t<::AZStd::ranges::Internal::maybe_const<Const, Views>>>>...>,
class = enable_if_t<Enable>>
friend constexpr auto operator!=(const iterator& x, const iterator& y) -> bool
{
return !(x == y);
}
template<bool Enable = ZipViewInternal::all_random_access<Const, Views...>, class = enable_if_t<Enable>>
friend constexpr auto operator<(const iterator& x, const iterator& y) -> bool
{
return x.m_current < y.m_current;
}
template<bool Enable = ZipViewInternal::all_random_access<Const, Views...>, class = enable_if_t<Enable>>
friend constexpr auto operator>(const iterator& x, const iterator& y) -> bool
{
return y.m_current < x.m_current;
}
template<bool Enable = ZipViewInternal::all_random_access<Const, Views...>, class = enable_if_t<Enable>>
friend constexpr auto operator<=(const iterator& x, const iterator& y) -> bool
{
return !(y.m_current < x.m_current);
}
template<bool Enable = ZipViewInternal::all_random_access<Const, Views...>, class = enable_if_t<Enable>>
friend constexpr auto operator>=(const iterator& x, const iterator& y) -> bool
{
return !(x.m_current < y.m_current);
}
/* Requires C++20 compiler support
friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires ZipViewInternal::all_random_access<Const, Views...> &&
(three_way_comparable<iterator_t<::AZStd::ranges::Internal::maybe_const<Const, Views>>> && ...);
*/
template<bool Enable = ZipViewInternal::all_random_access<Const, Views...>, class = enable_if_t<Enable>>
friend constexpr auto operator+(const iterator& i, difference_type n) -> iterator
{
auto r = i;
r += n;
return r;
}
template<bool Enable = ZipViewInternal::all_random_access<Const, Views...>, class = enable_if_t<Enable>>
friend constexpr auto operator+(difference_type n, const iterator& i) -> iterator
{
auto r = i;
r += n;
return r;
}
template<bool Enable = ZipViewInternal::all_random_access<Const, Views...>, class = enable_if_t<Enable>>
friend constexpr auto operator-(const iterator& i, difference_type n) -> iterator
{
auto r = i;
r -= n;
return r;
}
template<bool Enable = conjunction_v<
bool_constant<sized_sentinel_for<
iterator_t<::AZStd::ranges::Internal::maybe_const<Const, Views>>,
iterator_t<::AZStd::ranges::Internal::maybe_const<Const, Views>>>>...
>, class = enable_if_t<Enable>>
friend constexpr auto operator-(const iterator& x, const iterator& y) -> difference_type
{
return min_distance_in_views(x, y, AZStd::index_sequence_for<Views...>{});
}
// customization of iter_move and iter_swap
friend constexpr auto iter_move(
iterator& i) noexcept(
noexcept(ZipViewInternal::tuple_transform(ranges::iter_move, i.m_current)))
{
return ZipViewInternal::tuple_transform(ranges::iter_move, i.m_current);
}
friend constexpr auto iter_swap(
iterator& l,
iterator& r) noexcept
{
static_assert(!conjunction_v<
bool_constant<indirectly_swappable<iterator_t<::AZStd::ranges::Internal::maybe_const<Const, Views>>>>...>);
ZipViewInternal::tuple_zip(ranges::iter_swap, l.m_current, r.m_current,
AZStd::index_sequence_for<Views...>{});
}
private:
ZipViewInternal::tuple_or_pair<iterator_t<::AZStd::ranges::Internal::maybe_const<Const, Views>>...> m_current;
};
// sentinel type for iterator
template<class... Views>
template<bool Const>
class zip_view<Views...>::sentinel
: public enable_if_t<conjunction_v<
bool_constant<(sizeof...(Views) > 0)>,
bool_constant<input_range<Views>>...,
bool_constant<view<Views>>...
>, ZipViewInternal::requirements_fulfilled>
{
friend class zip_view<Views...>;
constexpr explicit sentinel(ZipViewInternal::tuple_or_pair<sentinel_t<::AZStd::ranges::Internal::maybe_const<Const, Views>>...> end);
template<bool OtherConst, size_t... Indices>
static constexpr auto min_distance_between_view_iterators(const iterator<OtherConst>& x,
const sentinel& y, AZStd::index_sequence<Indices...>) ->
common_type_t<range_difference_t<::AZStd::ranges::Internal::maybe_const<OtherConst, Views>>...>;
// On MSVC The friend functions are can only access the sentinel struct members
// The iterator struct which is a friend of the sentinel struct is NOT a friend
// of the friend functions
// So a shim is added to provide access to the iterator m_current member
template<bool OtherConst>
static constexpr auto iterator_accessor(const iterator<OtherConst>& it);
public:
sentinel() = default;
template<bool Enable = Const && conjunction_v<
bool_constant<convertible_to<sentinel_t<Views>, sentinel_t<::AZStd::ranges::Internal::maybe_const<Const, Views>>>>...>,
class = enable_if_t<Enable>>
constexpr sentinel(sentinel<!Const> i);
template<bool OtherConst, class = enable_if_t<conjunction_v<
bool_constant<sentinel_for<
sentinel_t<::AZStd::ranges::Internal::maybe_const<Const, Views>>,
iterator_t<::AZStd::ranges::Internal::maybe_const<OtherConst, Views>>>>...>
>>
friend constexpr auto operator==(const iterator<OtherConst>&x, const sentinel & y) -> bool
{
// Tracks if any iterator of the Views is equal to a sentinel of the views
bool anyIteratorEqual = false;
auto CompareIterator = [&anyIteratorEqual](auto&& lhs, auto&& rhs)
{
anyIteratorEqual = anyIteratorEqual || AZStd::forward<decltype(lhs)>(lhs) == AZStd::forward<decltype(rhs)>(rhs);
};
ZipViewInternal::tuple_zip(AZStd::move(CompareIterator), AZStd::index_sequence_for<Views...>{},
iterator_accessor(x), y.m_end);
return anyIteratorEqual;
}
template<bool OtherConst>
friend constexpr auto operator==(const sentinel & y, const iterator<OtherConst>&x) -> bool
{
return x == y;
}
template<bool OtherConst>
friend constexpr auto operator!=(const iterator<OtherConst>&x, const sentinel & y) -> bool
{
return !(x == y);
}
template<bool OtherConst>
friend constexpr auto operator!=(const sentinel & y, const iterator<OtherConst>&x) -> bool
{
return !(x == y);
}
template<bool OtherConst, class = enable_if_t<conjunction_v<
bool_constant<sentinel_for<
sentinel_t<::AZStd::ranges::Internal::maybe_const<Const, Views>>,
iterator_t<::AZStd::ranges::Internal::maybe_const<OtherConst, Views>>>>...>
>>
friend constexpr auto operator-(const iterator<OtherConst>&x, const sentinel & y) ->
common_type_t<range_difference_t<::AZStd::ranges::Internal::maybe_const<OtherConst, Views>>...>
{
return min_distance_between_view_iterators(x, y, AZStd::index_sequence_for<Views...>{});
}
template<bool OtherConst, class = enable_if_t<conjunction_v<
bool_constant<sentinel_for<
sentinel_t<::AZStd::ranges::Internal::maybe_const<Const, Views>>,
iterator_t<::AZStd::ranges::Internal::maybe_const<OtherConst, Views>>>>...>
>>
friend constexpr auto operator-(const sentinel & y, const iterator<OtherConst>&x) ->
common_type_t<range_difference_t<::AZStd::ranges::Internal::maybe_const<OtherConst, Views>>...>
{
return -(x - y);
}
private:
ZipViewInternal::tuple_or_pair<sentinel_t<::AZStd::ranges::Internal::maybe_const<Const, Views>>...> m_end;
};
} // namespace AZStd::ranges
#include <AzCore/std/ranges/zip_view.inl>

@ -0,0 +1,308 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/std/ranges/all_view.h>
#include <AzCore/std/ranges/ranges_algorithm.h>
#include <AzCore/std/tuple.h>
namespace AZStd::ranges
{
// public zip_view functions
template<class... Views>
constexpr zip_view<Views...>::zip_view(Views... views)
: m_views{ AZStd::move(views)... }
{
}
template<class... Views>
template<bool, class>
constexpr auto zip_view<Views...>::begin()
{
return iterator<false>(ZipViewInternal::tuple_transform(ranges::begin, m_views));
}
template<class... Views>
template<bool, class>
constexpr auto zip_view<Views...>::begin() const
{
return iterator<true>(ZipViewInternal::tuple_transform(ranges::begin, m_views));
}
template<class... Views>
template<bool, class>
constexpr auto zip_view<Views...>::end()
{
if constexpr (!ZipViewInternal::zip_is_common<Views...>)
{
return sentinel<false>(ZipViewInternal::tuple_transform(ranges::end, m_views));
}
else if constexpr ((random_access_range<Views> && ...))
{
return begin() + iter_difference_t<iterator<false>>(size());
}
else
{
return iterator<false>(ZipViewInternal::tuple_transform(ranges::end, m_views));
}
}
template<class... Views>
template<bool, class>
constexpr auto zip_view<Views...>::end() const
{
if constexpr (!ZipViewInternal::zip_is_common<const Views...>)
{
return sentinel<true>(ZipViewInternal::tuple_transform(ranges::end, m_views));
}
else if constexpr ((random_access_range<const Views> && ...))
{
return begin() + iter_difference_t<iterator<true>>(size());
}
else
{
return iterator<true>(ZipViewInternal::tuple_transform(ranges::end, m_views));
}
}
template<class... Views>
template<bool, class>
constexpr auto zip_view<Views...>::size()
{
auto GetSizeForViews = [](auto... sizes)
{
using CommonType = make_unsigned_t<common_type_t<decltype(sizes)...>>;
return ranges::min({ CommonType(sizes)... });
};
return AZStd::apply(AZStd::move(GetSizeForViews), ZipViewInternal::tuple_transform(ranges::size, m_views));
}
template<class... Views>
template<bool, class>
constexpr auto zip_view<Views...>::size() const
{
auto GetSizeForViews = [](auto... sizes)
{
using CommonType = make_unsigned_t<common_type_t<decltype(sizes)...>>;
return ranges::min({ CommonType(sizes)... });
};
return AZStd::apply(AZStd::move(GetSizeForViews), ZipViewInternal::tuple_transform(ranges::size, m_views));
}
// public zip_view::iterator functions
template<class... Views>
template<bool Const>
template<bool, class>
constexpr zip_view<Views...>::iterator<Const>::iterator(iterator<!Const> other)
: m_current(AZStd::move(other.m_current))
{
}
template<class... Views>
template<bool Const>
constexpr auto zip_view<Views...>::iterator<Const>::operator*() const
{
auto TransformToReference = [](auto& i) -> decltype(auto)
{
return *i;
};
return ZipViewInternal::tuple_transform(AZStd::move(TransformToReference), m_current);
}
template<class... Views>
template<bool Const>
constexpr auto zip_view<Views...>::iterator<Const>::operator++() -> iterator&
{
auto PreIncrementIterator = [](auto& i)
{
++i;
};
ZipViewInternal::tuple_for_each(AZStd::move(PreIncrementIterator), m_current);
return *this;
}
template<class... Views>
template<bool Const>
constexpr decltype(auto) zip_view<Views...>::iterator<Const>::operator++(int)
{
if constexpr (ZipViewInternal::all_forward<Const, Views...>)
{
auto tmp = *this;
++(*this);
return tmp;
}
else
{
++(*this);
}
}
template<class... Views>
template<bool Const>
template<bool, class>
constexpr auto zip_view<Views...>::iterator<Const>::operator--() -> iterator&
{
auto PreDecrementIterator = [](auto& i)
{
--i;
};
ZipViewInternal::tuple_for_each(AZStd::move(PreDecrementIterator), m_current);
return *this;
}
template<class... Views>
template<bool Const>
template<bool, class>
constexpr auto zip_view<Views...>::iterator<Const>::operator--(int) -> iterator
{
auto tmp = *this;
--* this;
return tmp;
}
template<class... Views>
template<bool Const>
template<bool, class>
constexpr auto zip_view<Views...>::iterator<Const>::operator+=(difference_type x) -> iterator&
{
auto AddIterator = [&](auto& i)
{
i += iter_difference_t<decltype(i)>(x);
};
ZipViewInternal::tuple_for_each(AZStd::move(AddIterator), m_current);
return *this;
}
template<class... Views>
template<bool Const>
template<bool, class>
constexpr auto zip_view<Views...>::iterator<Const>::operator-=(difference_type x) -> iterator&
{
auto AddIterator = [&](auto& i)
{
i -= iter_difference_t<decltype(i)>(x);
};
ZipViewInternal::tuple_for_each(AZStd::move(AddIterator), m_current);
return *this;
}
template<class... Views>
template<bool Const>
template<bool, class>
constexpr auto zip_view<Views...>::iterator<Const>::operator[](difference_type n) const
{
return view_iterator_to_value_tuple(n);
}
// private zip_view::iterator functions
template<class... Views>
template<bool Const>
constexpr zip_view<Views...>::iterator<Const>::iterator(
ZipViewInternal::tuple_or_pair<iterator_t<::AZStd::ranges::Internal::maybe_const<Const, Views>>...> current)
: m_current(AZStd::move(current))
{
}
template<class... Views>
template<bool Const>
constexpr auto zip_view<Views...>::iterator<Const>::view_iterator_to_value_tuple(difference_type n) const
{
auto TransformToValue = [&](auto& i) -> decltype(auto)
{
using I = decltype(i);
return i[iter_difference_t<I>(n)];
};
return ZipViewInternal::tuple_transform(AZStd::move(TransformToValue), m_current);
}
template<class... Views>
template<bool Const>
template<size_t... Indices>
constexpr auto zip_view<Views...>::iterator<Const>::any_iterator_equal(const iterator& x, const iterator& y,
AZStd::index_sequence<Indices...>)
{
return (... || (AZStd::get<Indices>(x.m_current) == AZStd::get<Indices>(y.m_current)));
}
template<class... Views>
template<bool Const>
template<size_t... Indices>
constexpr auto zip_view<Views...>::iterator<Const>::min_distance_in_views(const iterator& x, const iterator& y,
AZStd::index_sequence<Indices...>)
{
AZStd::array iterDistances{
((AZStd::get<Indices>(x.m_current) - AZStd::get<Indices>(y.m_current)), ...) };
if (iterDistances.empty())
{
return difference_type{};
}
auto first = iterDistances.begin();
difference_type minDistance = *first++;
auto last = iterDistances.end();
for (; first != last; ++first)
{
difference_type absMinDistance = minDistance < 0 ? -minDistance : minDistance;
difference_type absDistance = *first < 0 ? -*first : *first;
minDistance = absDistance < absMinDistance ? *first : minDistance;
}
return minDistance;
}
// private zip_view::sentinel functions
template<class... Views>
template<bool Const>
constexpr zip_view<Views...>::sentinel<Const>::sentinel(
ZipViewInternal::tuple_or_pair<sentinel_t<::AZStd::ranges::Internal::maybe_const<Const, Views>>...> end)
: m_end(end)
{
}
template<class... Views>
template<bool Const>
template<bool, class>
constexpr zip_view<Views...>::sentinel<Const>::sentinel(sentinel<!Const> other)
: m_end(AZStd::move(other.m_end))
{
}
template<class... Views>
template<bool Const>
template<bool OtherConst, size_t... Indices>
constexpr auto zip_view<Views...>::sentinel<Const>::min_distance_between_view_iterators(
const typename zip_view<Views...>::template iterator<OtherConst>& x,
const typename zip_view<Views...>::template sentinel<Const>& y,
AZStd::index_sequence<Indices...>) ->
common_type_t<range_difference_t<::AZStd::ranges::Internal::maybe_const<OtherConst, Views>>...>
{
using difference_type = common_type_t<range_difference_t<::AZStd::ranges::Internal::maybe_const<OtherConst, Views>>...>;
// Tracks if any iterator of the Views is equal to a sentinel of the views
AZStd::array iterDistances{
((AZStd::get<Indices>(x.m_current) - AZStd::get<Indices>(y.m_end)), ...) };
if (iterDistances.empty())
{
return difference_type{};
}
auto first = iterDistances.begin();
difference_type minDistance = *first++;
auto last = iterDistances.end();
for (; first != last; ++first)
{
difference_type absMinDistance = minDistance < 0 ? -minDistance : minDistance;
difference_type absDistance = *first < 0 ? -*first : *first;
minDistance = absDistance < absMinDistance ? *first : minDistance;
}
return minDistance;
}
template<class... Views>
template<bool Const>
template<bool OtherConst>
constexpr auto zip_view<Views...>::sentinel<Const>::iterator_accessor(const iterator<OtherConst>& it)
{
return it.m_current;
}
} // namespace AZStd::ranges

@ -603,6 +603,23 @@ namespace AZStd
template <class Element, class Traits = AZStd::char_traits<Element>>
class basic_string_view
{
template <class R, class = void>
static constexpr bool has_operator_basic_string_view = false;
template <class R>
static constexpr bool has_operator_basic_string_view<R, void_t<
decltype(declval<remove_cvref_t<R>>().operator basic_string_view<Element, Traits>())
>> = true;
// If the range has a traits_type element, it must match
template <class R, class = void>
static constexpr bool range_trait_type_matches = true;
template <class R>
static constexpr bool range_trait_type_matches<R,
enable_if_t<conjunction_v<
Internal::sfinae_trigger<typename remove_reference_t<R>::traits_type>,
bool_constant<!same_as<typename remove_reference_t<R>::traits_type, Traits>>
>>> = false;
public:
using traits_type = Traits;
using value_type = Element;
@ -646,6 +663,25 @@ namespace AZStd
, m_size(AZStd::to_address(last) - AZStd::to_address(first))
{}
// double SFINAE is used to defer evaluation of the contiguous range
// until after validating the input type isn't basic_string_view
template <typename R,
typename = enable_if_t<conjunction_v<
bool_constant<!same_as<remove_cvref_t<R>, basic_string_view>>,
bool_constant<!convertible_to<const_pointer, R>>
>>,
typename = enable_if_t<conjunction_v<
bool_constant<ranges::contiguous_range<R>>,
bool_constant<ranges::sized_range<R>>,
bool_constant<same_as<ranges::range_value_t<R>, value_type>>,
bool_constant<!has_operator_basic_string_view<R>>,
bool_constant<range_trait_type_matches<R>>
>>>
constexpr basic_string_view(R&& r)
: m_begin(ranges::data(r))
, m_size(ranges::size(r))
{}
constexpr basic_string_view(const basic_string_view&) noexcept = default;
constexpr basic_string_view(basic_string_view&& other)
{
@ -982,6 +1018,11 @@ namespace AZStd
size_type m_size{};
};
template<class It, class End>
basic_string_view(It, End)->basic_string_view<iter_value_t<It>>;
template<class R>
basic_string_view(R&&)->basic_string_view<ranges::range_value_t<R>>;
using string_view = basic_string_view<char>;
using wstring_view = basic_string_view<wchar_t>;

@ -19,22 +19,14 @@
namespace AZStd
{
template<class... Types>
using tuple = std::tuple<Types...>;
template<class T>
using tuple_size = std::tuple_size<T>;
template<size_t I, class T>
using tuple_element = std::tuple_element<I, T>;
template<size_t I, class T>
using tuple_element_t = typename std::tuple_element<I, T>::type;
using std::tuple;
using std::tuple_size;
using std::tuple_size_v;
using std::tuple_element;
using std::tuple_element_t;
// Placeholder structure that can be assigned any value with no effect.
// This is used by AZStd::tie as placeholder for unused arugments
using ignore_t = AZStd::decay_t<decltype(std::ignore)>;
decltype(std::ignore) ignore = std::ignore;
using std::ignore;
using std::make_tuple;
using std::tie;

@ -7,30 +7,10 @@
*/
#pragma once
#include <AzCore/std/typetraits/typetraits.h>
#include <AzCore/std/typetraits/conditional.h>
#include <AzCore/std/typetraits/integral_constant.h> // for true_type
#include <type_traits>
namespace AZStd
{
template<class... Bases>
struct conjunction
: true_type
{
};
template<class B1>
struct conjunction<B1>
: B1
{
};
template<class B1, class... Bases>
struct conjunction<B1, Bases...>
: conditional_t<!B1::value, B1, conjunction<Bases...>>
{
};
template<class... Bases>
constexpr bool conjunction_v = conjunction<Bases...>::value;
using std::conjunction;
using std::conjunction_v;
} // namespace AZStd

@ -7,29 +7,10 @@
*/
#pragma once
#include <AzCore/std/typetraits/integral_constant.h>
#include <AzCore/std/typetraits/conditional.h>
#include <type_traits>
namespace AZStd
{
template<class... Bases>
struct disjunction
: false_type
{
};
template<class B1>
struct disjunction<B1>
: B1
{
};
template<class B1, class... Bases>
struct disjunction<B1, Bases...>
: conditional_t<B1::value, B1, disjunction<Bases...>>
{
};
template<class... Bases>
constexpr bool disjunction_v = disjunction<Bases...>::value;
using std::disjunction;
using std::disjunction_v;
}

@ -13,49 +13,30 @@
namespace AZStd
{
using std::is_constructible;
using std::is_constructible_v;
using std::is_trivially_constructible;
using std::is_trivially_constructible_v;
using std::is_nothrow_constructible;
using std::is_nothrow_constructible_v;
using std::is_default_constructible;
using std::is_default_constructible_v;
using std::is_trivially_default_constructible;
using std::is_trivially_default_constructible_v;
using std::is_nothrow_default_constructible;
using std::is_nothrow_default_constructible_v;
using std::is_copy_constructible;
using std::is_copy_constructible_v;
using std::is_trivially_copy_constructible;
using std::is_trivially_copy_constructible_v;
using std::is_nothrow_copy_constructible;
using std::is_nothrow_copy_constructible_v;
using std::is_move_constructible;
using std::is_move_constructible_v;
using std::is_trivially_move_constructible;
using std::is_trivially_move_constructible_v;
using std::is_nothrow_move_constructible;
template<class T, class... Args>
constexpr bool is_constructible_v = std::is_constructible<T, Args...>::value;
template<class T, class... Args>
constexpr bool is_trivially_constructible_v = std::is_trivially_constructible<T, Args...>::value;
template<class T, class... Args>
constexpr bool is_nothrow_constructible_v = std::is_nothrow_constructible<T, Args...>::value;
template<class T>
constexpr bool is_default_constructible_v = std::is_default_constructible<T>::value;
template<class T>
constexpr bool is_trivially_default_constructible_v = std::is_trivially_default_constructible<T>::value;
template<class T>
constexpr bool is_nothrow_default_constructible_v = std::is_nothrow_default_constructible<T>::value;
template<class T>
constexpr bool is_copy_constructible_v = std::is_copy_constructible<T>::value;
template<class T>
constexpr bool is_trivially_copy_constructible_v = std::is_trivially_copy_constructible<T>::value;
template<class T>
constexpr bool is_nothrow_copy_constructible_v = std::is_nothrow_copy_constructible<T>::value;
template<class T>
constexpr bool is_move_constructible_v = std::is_move_constructible<T>::value;
template<class T>
constexpr bool is_trivially_move_constructible_v = std::is_trivially_move_constructible<T>::value;
template<class T>
constexpr bool is_nothrow_move_constructible_v = std::is_nothrow_move_constructible<T>::value;
using std::is_nothrow_move_constructible_v;
}

@ -7,16 +7,10 @@
*/
#pragma once
#include <AzCore/std/typetraits/integral_constant.h>
#include <type_traits>
namespace AZStd
{
template<class B>
struct negation
: integral_constant<bool, !B::value>
{
};
template<class B>
constexpr bool negation_v = negation<B>::value;
using std::negation;
using std::negation_v;
}

@ -92,36 +92,13 @@ namespace AZStd
//////////////////////////////////////////////////////////////////////////
// The structure that encapsulates index lists
template <size_t... Is>
struct index_sequence
{
static constexpr size_t size = sizeof...(Is);
};
// Collects internal details for generating index ranges [MIN, MAX)
namespace Internal
{
// Declare primary template for index range builder
template <size_t MIN, size_t N, size_t... Is>
struct range_builder;
// Base step
template <size_t MIN, size_t... Is>
struct range_builder<MIN, MIN, Is...>
{
typedef index_sequence<Is...> type;
};
// Induction step
template <size_t MIN, size_t N, size_t... Is>
struct range_builder : public range_builder<MIN, N - 1, N - 1, Is...>
{
};
}
using std::integer_sequence;
using std::index_sequence;
using std::index_sequence_for;
// Create index range [0,N]
template<size_t N>
using make_index_sequence = typename Internal::range_builder<0, N>::type;
using std::make_index_sequence;
using std::make_integer_sequence;
struct piecewise_construct_t {};
static constexpr piecewise_construct_t piecewise_construct{};
@ -279,31 +256,7 @@ namespace AZStd
//////////////////////////////////////////////////////////////////////////
// Address of
//////////////////////////////////////////////////////////////////////////
namespace Internal
{
template<class T>
struct addr_impl_ref
{
T& m_v;
constexpr addr_impl_ref(T& v)
: m_v(v) {}
constexpr addr_impl_ref& operator=(const addr_impl_ref& v) { m_v = v; return *this; }
constexpr operator T& () const { return m_v; }
};
template<class T>
struct addressof_impl
{
static AZ_FORCE_INLINE T* f(T& v, long) { return reinterpret_cast<T*>(&const_cast<char&>(reinterpret_cast<const volatile char&>(v))); }
static constexpr T* f(T* v, int) { return v; }
};
}
template<class T>
T* addressof(T& v)
{
return Internal::addressof_impl<T>::f(Internal::addr_impl_ref<T>(v), 0);
}
using std::addressof;
// End addressof
//////////////////////////////////////////////////////////////////////////
@ -446,57 +399,14 @@ namespace AZStd
};
#endif
template <template <class> class, typename...>
struct sequence_and;
using std::in_place_t;
using std::in_place;
template <template <class> class trait, typename T1, typename... Ts>
struct sequence_and<trait, T1, Ts...>
{
static const bool value = trait<T1>::value && sequence_and<trait, Ts...>::value;
};
template <template <class> class trait>
struct sequence_and<trait>
{
static const bool value = true;
};
template <template <class> class, typename...>
struct sequence_or;
using std::in_place_type_t;
using std::in_place_type;
template <template <class> class trait, typename T1, typename... Ts>
struct sequence_or<trait, T1, Ts...>
{
static const bool value = trait<T1>::value || sequence_or<trait, Ts...>::value;
};
template <template <class> class trait>
struct sequence_or<trait>
{
static const bool value = false;
};
struct in_place_t
{
explicit constexpr in_place_t() = default;
};
constexpr in_place_t in_place{};
template<typename T>
struct in_place_type_t
{
explicit constexpr in_place_type_t() = default;
};
template <typename T>
constexpr in_place_type_t<T> in_place_type{};
template<size_t I>
struct in_place_index_t
{
explicit constexpr in_place_index_t() = default;
};
template<size_t I>
constexpr in_place_index_t<I> in_place_index{};
using std::in_place_index_t;
using std::in_place_index;
namespace Internal
{

@ -140,7 +140,7 @@ namespace AZ {
SymRegisterCallback64_t g_SymRegisterCallback64;
HMODULE g_dbgHelpDll;
#define LOAD_FUNCTION(A) { g_##A = (A##_t)GetProcAddress(g_dbgHelpDll, #A); AZ_Assert(g_##A != 0, ("Can not load %s function!",#A)); }
#define LOAD_FUNCTION(A) { g_##A = (A##_t)GetProcAddress(g_dbgHelpDll, #A); AZ_Assert(g_##A != 0, "Can not load %s function!",#A); }
using namespace AZ::Debug;
@ -596,7 +596,7 @@ namespace AZ {
result = GetLastError();
}
ULONGLONG fileVersion = 0;
if (szImg != NULL)
if (szImg[0]) // !szImg.empty()
{
// try to retrieve the file-version:
VS_FIXEDFILEINFO* fInfo = NULL;
@ -624,43 +624,6 @@ namespace AZ {
}
}
// Retrive some additional-infos about the module
IMAGEHLP_MODULE64 Module;
const char* szSymType = "-unknown-";
if (GetModuleInfo(hProcess, baseAddr, &Module) != FALSE)
{
switch (Module.SymType)
{
case SymNone:
szSymType = "-nosymbols-";
break;
case SymCoff:
szSymType = "COFF";
break;
case SymCv:
szSymType = "CV";
break;
case SymPdb:
szSymType = "PDB";
break;
case SymExport:
szSymType = "-exported-";
break;
case SymDeferred:
szSymType = "-deferred-";
break;
case SymSym:
szSymType = "SYM";
break;
case 8: //SymVirtual:
szSymType = "Virtual";
break;
case 9: // SymDia:
szSymType = "DIA";
break;
}
}
// find insert position
if (g_moduleInfo.size() < g_moduleInfo.capacity())
{
@ -1073,7 +1036,7 @@ cleanup:
}
HANDLE hThread = nativeThread;
CONTEXT alignas(8) context; // Without this alignment the function randomly crashes in release.
alignas(alignof(CONTEXT)) CONTEXT context; // Without this alignment the function randomly crashes in release.
context.ContextFlags = CONTEXT_ALL;
GetThreadContext(hThread, &context);

@ -8,6 +8,7 @@
#include <AzCore/UnitTest/TestTypes.h>
#include <AzCore/std/concepts/concepts.h>
#include <AzCore/std/ranges/ranges_functional.h>
namespace UnitTest
{
@ -199,4 +200,122 @@ namespace UnitTest
static_assert(!AZStd::strict_weak_order<RelationPredicate, int, Base>);
static_assert(!AZStd::strict_weak_order<RelationPredicate, Base, int>);
}
TEST_F(ConceptsTestFixture, IteratorInvocableConcepts)
{
// concept indirectly unary invocable
// i.e Is deferencing an iterator like type and invoking
// a unary callable a well formed expression
auto CharUnaryCallable = [](const char) -> int { return {}; };
auto IntUnaryCallable = [](int) -> int { return {}; };
auto IntRefUnaryCallable = [](int&) -> int { return {}; };
static_assert(AZStd::indirectly_unary_invocable<decltype(CharUnaryCallable), AZStd::string_view::iterator>);
static_assert(AZStd::indirectly_unary_invocable<decltype(IntUnaryCallable), AZStd::string_view::iterator>);
static_assert(!AZStd::indirectly_unary_invocable<decltype(IntRefUnaryCallable), AZStd::string_view::iterator>);
// concept indirectly regular unary invocable
// i.e Is deferencing an iterator like type and invoking with a unary callable
// which will not modify the input arguments(hence the term "regular") a well formed expression
static_assert(AZStd::indirectly_regular_unary_invocable<decltype(CharUnaryCallable), AZStd::string_view::iterator>);
static_assert(AZStd::indirectly_regular_unary_invocable<decltype(IntUnaryCallable), AZStd::string_view::iterator>);
static_assert(!AZStd::indirectly_regular_unary_invocable<decltype(IntRefUnaryCallable), AZStd::string_view::iterator>);
// concept indirect unary predicate
// i.e Is deferencing an iterator like type and invoking with a unary predicate
// i.e which is a callable that accepts one argument and returns value testable in a boolean context
auto CharUnaryPredicate = [](const char) -> bool { return {}; };
auto IntUnaryPredicate = [](int) -> int { return {}; };// Return value is an int which is convertible to bool
auto IntRefUnaryPredicate = [](int&) -> int { return {}; }; // string_view iterator value type(char) can't bind to an int&
auto CharUnaryNonPredicate = [](const char) -> AZStd::string_view { return {}; }; // string_view is not convertible to bool
static_assert(AZStd::indirect_unary_predicate<decltype(CharUnaryPredicate), AZStd::string_view::iterator>);
static_assert(AZStd::indirect_unary_predicate<decltype(IntUnaryPredicate), AZStd::string_view::iterator>);
static_assert(!AZStd::indirect_unary_predicate<decltype(IntRefUnaryPredicate), AZStd::string_view::iterator>);
static_assert(!AZStd::indirect_unary_predicate<decltype(CharUnaryNonPredicate), AZStd::string_view::iterator>);
// concept indirect binary predicate
// i.e Is deferencing two iterator like types and invoking a binary predicate with those values
// well formed and returns value testable in a boolean context.
auto CharIntBinaryPredicate = [](const char, int) -> bool { return{}; };
auto CharCharRefBinaryPredicate = [](const char, const char&) -> uint32_t { return{}; };
auto UIntRefCharBinaryPredicate = [](uint32_t&, char) -> bool { return{}; };
auto CharCharBinaryNonPredicate = [](const char, const char) -> AZStd::string_view { return {}; };
static_assert(AZStd::indirect_binary_predicate<decltype(CharIntBinaryPredicate),
AZStd::string_view::iterator, AZStd::string_view::iterator>);
static_assert(AZStd::indirect_binary_predicate<decltype(CharCharRefBinaryPredicate),
AZStd::string_view::iterator, AZStd::string_view::iterator>);
// string_view iterator value type(char) cannot bind to int&
static_assert(!AZStd::indirect_binary_predicate<decltype(UIntRefCharBinaryPredicate),
AZStd::string_view::iterator, AZStd::string_view::iterator>);
// string_view is not convertible to bool
static_assert(!AZStd::indirect_binary_predicate<decltype(CharCharBinaryNonPredicate),
AZStd::string_view::iterator, AZStd::string_view::iterator>);
// Ok - iter_reference_t<uint32_t*> = uint32_t&
static_assert(AZStd::indirect_binary_predicate<decltype(UIntRefCharBinaryPredicate),
uint32_t*, AZStd::string_view::iterator>);
// concept indirect equivalence relation
// i.e Is deferencing two iterator like types and invoking a binary predicate with those values
// well formed and returns value testable in a boolean context.
// The dereferenced iterator types should be model an equivalence relationship
// (a == b) && (b == c) == (a ==c)
static_assert(AZStd::indirect_equivalence_relation<decltype(CharIntBinaryPredicate),
AZStd::string_view::iterator, AZStd::string_view::iterator>);
static_assert(AZStd::indirect_equivalence_relation<decltype(CharCharRefBinaryPredicate),
AZStd::string_view::iterator, AZStd::string_view::iterator>);
static_assert(!AZStd::indirect_equivalence_relation<decltype(UIntRefCharBinaryPredicate),
AZStd::string_view::iterator, AZStd::string_view::iterator>);
static_assert(!AZStd::indirect_equivalence_relation<decltype(CharCharBinaryNonPredicate),
AZStd::string_view::iterator, AZStd::string_view::iterator>);
// The "relation" concept requires that both both arguments can be bind to
// either of the two binary parameters
static_assert(!AZStd::indirect_equivalence_relation<decltype(UIntRefCharBinaryPredicate),
uint32_t*, AZStd::string_view::iterator>);
// concept indirect strict weak order
// i.e Is deferencing two iterator like types and invoking a binary predicate with those values
// well formed and returns value testable in a boolean context.
// The dereferenced iterator types should be model a strict weak order relation
// (a < b) && (b < c) == (a < c)
static_assert(AZStd::indirect_strict_weak_order<decltype(CharIntBinaryPredicate),
AZStd::string_view::iterator, AZStd::string_view::iterator>);
static_assert(AZStd::indirect_strict_weak_order<decltype(CharCharRefBinaryPredicate),
AZStd::string_view::iterator, AZStd::string_view::iterator>);
static_assert(!AZStd::indirect_strict_weak_order<decltype(UIntRefCharBinaryPredicate),
AZStd::string_view::iterator, AZStd::string_view::iterator>);
static_assert(!AZStd::indirect_strict_weak_order<decltype(CharCharBinaryNonPredicate),
AZStd::string_view::iterator, AZStd::string_view::iterator>);
// The "relation" concept requires that both both arguments can be bind to
// either of the two binary parameters
static_assert(!AZStd::indirect_strict_weak_order<decltype(UIntRefCharBinaryPredicate),
uint32_t*, AZStd::string_view::iterator>);
// indirect_result_t type alias
static_assert(AZStd::same_as<AZStd::indirect_result_t<decltype(CharCharRefBinaryPredicate),
AZStd::string_view::iterator, const char*>, uint32_t>);
// projected operator* returns indirect result of the projection function
static_assert(AZStd::same_as<AZStd::iter_reference_t<AZStd::projected<int*, AZStd::identity>>, int&>);
}
TEST_F(ConceptsTestFixture, IteratorAlgorithmConcepts)
{
static_assert(AZStd::indirectly_swappable<int*, int*>);
static_assert(!AZStd::indirectly_swappable<int*, const int*>);
auto CharIntIndirectlyComparable = [](const char lhs, int rhs) -> bool { return lhs == rhs; };
static_assert(AZStd::indirectly_comparable<const char*, int*, decltype(CharIntIndirectlyComparable)>);
static_assert(!AZStd::indirectly_comparable<AZStd::string_view, int*, decltype(CharIntIndirectlyComparable)>);
static_assert(AZStd::permutable<typename AZStd::vector<int>::iterator>);
// const iterator isn't indirectlly swappable or indirectly movable
static_assert(!AZStd::permutable<typename AZStd::vector<int>::const_iterator>);
static_assert(AZStd::mergeable<AZStd::vector<int>::iterator, AZStd::string_view::iterator, AZStd::vector<int>::iterator>);
static_assert(!AZStd::mergeable<AZStd::vector<int>::iterator, AZStd::string_view::iterator, AZStd::string_view::iterator>);
static_assert(AZStd::sortable<int*>);
// Not sortable becaue the iter_reference_t<const int*> = const int& which isn't swappable
static_assert(!AZStd::sortable<const int*>);
}
}

@ -443,7 +443,7 @@ namespace UnitTest
: m_data(data) { /* expensive operations */ }
private:
int m_data;
[[maybe_unused]] int m_data;
};
//////////////////////////////////////////////////////////////////////////

@ -0,0 +1,250 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzCore/UnitTest/TestTypes.h>
#include <AzCore/std/string/string_view.h>
#include <AzCore/std/ranges/ranges_algorithm.h>
namespace UnitTest
{
class RangesAlgorithmTestFixture
: public ScopedAllocatorSetupFixture
{};
// range algorithm min and max
TEST_F(RangesAlgorithmTestFixture, RangesMin_ReturnsSmallestElement)
{
// Simple Elements
EXPECT_EQ(-1, AZStd::ranges::min(5, -1));
EXPECT_EQ(78235, AZStd::ranges::min(78235, 124785));
EXPECT_EQ(7, AZStd::ranges::min(7, 7));
// Initializer list
AZStd::initializer_list<int> testIList{ 5, 1, 22, 47, -8, -5, 1000, 687, 22, -8, 1000, 45 };
EXPECT_EQ(-8, AZStd::ranges::min(testIList));
// Range
AZStd::vector testVector{ 5, 1, 22, 47, -8, -5, 1000, 687, 22, -8, 1000, 45 };
EXPECT_EQ(-8, AZStd::ranges::min(testVector));
}
TEST_F(RangesAlgorithmTestFixture, RangesMax_ReturnsLargestElement)
{
// Simple Elements
EXPECT_EQ(5, AZStd::ranges::max(5, -1));
EXPECT_EQ(124785, AZStd::ranges::max(78235, 124785));
EXPECT_EQ(7, AZStd::ranges::max(7, 7));
// Initializer list
AZStd::initializer_list<int> testIList{ 5, 1, 22, 47, -8, -5, 1000, 687, 22, -8, 1000, 45 };
EXPECT_EQ(1000, AZStd::ranges::max(testIList));
// Range
AZStd::vector testVector{ 5, 1, 22, 47, -8, -5, 1000, 687, 22, -8, 1000, 45 };
EXPECT_EQ(1000, AZStd::ranges::max(testVector));
}
TEST_F(RangesAlgorithmTestFixture, RangesMinMax_ReturnsSmallestAndLargestValue)
{
// Simple Elements
AZStd::ranges::minmax_result<int> expectedMinMax{ -1, 5 };
AZStd::ranges::minmax_result<int> testMinMax = AZStd::ranges::minmax(5, -1);
EXPECT_EQ(expectedMinMax.min, testMinMax.min);
EXPECT_EQ(expectedMinMax.max, testMinMax.max);
expectedMinMax = { 78235, 124785 };
testMinMax = AZStd::ranges::minmax(78235, 124785);
EXPECT_EQ(expectedMinMax.min, testMinMax.min);
EXPECT_EQ(expectedMinMax.max, testMinMax.max);
expectedMinMax = { 7, 7 };
testMinMax = AZStd::ranges::minmax(7, 7);
EXPECT_EQ(expectedMinMax.min, testMinMax.min);
EXPECT_EQ(expectedMinMax.max, testMinMax.max);
// Initializer list
AZStd::initializer_list<int> testIList{ 5, 1, 22, 47, -8, -5, 1000, 687, 22, -8, 1000, 45 };
expectedMinMax = { -8, 1000 };
testMinMax = AZStd::ranges::minmax(testIList);
EXPECT_EQ(expectedMinMax.min, testMinMax.min);
EXPECT_EQ(expectedMinMax.max, testMinMax.max);
// Range
AZStd::vector testVector{ 5, 1, 22, 47, -8, -5, 1000, 687, 22, -8, 1000, 45 };
expectedMinMax = { -8, 1000 };
testMinMax = AZStd::ranges::minmax(testVector);
EXPECT_EQ(expectedMinMax.min, testMinMax.min);
EXPECT_EQ(expectedMinMax.max, testMinMax.max);
}
TEST_F(RangesAlgorithmTestFixture, RangesMinElement_ReturnsIteratorToLeftmostSmallestElement)
{
AZStd::vector testVector{ 5, 1, 22, 47, -8, -5, 1000, 687, 22, -8, 1000, 45 };
// iterator
auto leftmostSmallestIt = AZStd::ranges::min_element(testVector.begin(), testVector.end());
ASSERT_EQ(testVector.begin() + 4, leftmostSmallestIt);
EXPECT_EQ(-8, *leftmostSmallestIt);
// Range
leftmostSmallestIt = AZStd::ranges::min_element(testVector);
ASSERT_EQ(testVector.begin() + 4, leftmostSmallestIt);
EXPECT_EQ(-8, *leftmostSmallestIt);
}
TEST_F(RangesAlgorithmTestFixture, RangesMaxElement_ReturnsIteratorToLeftmostLargestElement)
{
AZStd::vector testVector{ 5, 1, 22, 47, -8, -5, 1000, 687, 22, -8, 1000, 45 };
// iterator
auto leftmostLargestIt = AZStd::ranges::max_element(testVector.begin(), testVector.end());
ASSERT_EQ(testVector.begin() + 6, leftmostLargestIt);
EXPECT_EQ(1000, *leftmostLargestIt);
// Range
leftmostLargestIt = AZStd::ranges::max_element(testVector);
ASSERT_EQ(testVector.begin() + 6, leftmostLargestIt);
EXPECT_EQ(1000, *leftmostLargestIt);
}
TEST_F(RangesAlgorithmTestFixture, RangesMinMaxElement_ReturnsIteratorToLeftmostSmallestElement_IteratorToRightmostLargestElement)
{
// The behavior of minmax_element is explicitly different from max_element
// as it relates to the max element being returned
// mixmax_element returns the rightmost largest element(assuming comparison function object is ranges::less)
// https://eel.is/c++draft/algorithms#footnoteref-225
AZStd::vector testVector{ 5, 1, 22, 47, -8, -5, 1000, 687, 22, -8, 1000, 45 };
// iterator
{
auto [leftmostSmallestIt, rightmostLargestIt] = AZStd::ranges::minmax_element(testVector.begin(), testVector.end());
ASSERT_EQ(testVector.begin() + 4, leftmostSmallestIt);
ASSERT_EQ(testVector.begin() + 10, rightmostLargestIt);
EXPECT_EQ(-8, *leftmostSmallestIt);
EXPECT_EQ(1000, *rightmostLargestIt);
}
// Range
auto [leftmostSmallestIt, rightmostLargestIt] = AZStd::ranges::minmax_element(testVector);
ASSERT_EQ(testVector.begin() + 4, leftmostSmallestIt);
ASSERT_EQ(testVector.begin() + 10, rightmostLargestIt);
EXPECT_EQ(-8, *leftmostSmallestIt);
EXPECT_EQ(1000, *rightmostLargestIt);
}
TEST_F(RangesAlgorithmTestFixture, RangesFind_LocatesElementInContainer_Succeeds)
{
AZStd::vector testVector{ 5, 1, 22, 47, -8, -5, 1000, 687, 22, -8, 1000, 45 };
auto foundIt = AZStd::ranges::find(testVector, 22);
ASSERT_NE(testVector.end(), foundIt);
EXPECT_EQ(22, *foundIt);
foundIt = AZStd::ranges::find_if(testVector, [](int value) { return value < 0; });
ASSERT_NE(testVector.end(), foundIt);
EXPECT_EQ(-8, *foundIt);
foundIt = AZStd::ranges::find_if_not(testVector, [](int value) { return value < 1000; });
ASSERT_NE(testVector.end(), foundIt);
EXPECT_EQ(1000, *foundIt);
}
TEST_F(RangesAlgorithmTestFixture, RangesFindFirstOf_LocatesElementInContainer_Succeeds)
{
AZStd::vector testVector{ 5, 1, 22, 47, -8, -5, 1000, 687, 22, -8, 1000, 45 };
AZStd::array testArray{ -8, 47 };
auto foundIt = AZStd::ranges::find_first_of(testVector, testArray);
ASSERT_NE(testVector.end(), foundIt);
EXPECT_EQ(47, *foundIt);
AZStd::array<int, 0> emptyArray{};
foundIt = AZStd::ranges::find_first_of(testVector, emptyArray);
EXPECT_EQ(testVector.end(), foundIt);
}
TEST_F(RangesAlgorithmTestFixture, RangesSearch_LocatesElementInContainer_Succeeds)
{
AZStd::vector testVector{ 5, 1, 22, 47, -8, -5, 1000, 687, 22, -8, -8, 1000, 45 };
AZStd::array testArray{ 1000 };
auto testSubrange = AZStd::ranges::search(testVector, testArray);
ASSERT_FALSE(testSubrange.empty());
EXPECT_EQ(1000, testSubrange.front());
AZStd::array testArray2{ 1000, 45 };
testSubrange = AZStd::ranges::search(testVector, testArray2);
ASSERT_EQ(2, testSubrange.size());
EXPECT_EQ(1000, testSubrange[0]);
EXPECT_EQ(45, testSubrange[1]);
testSubrange = AZStd::ranges::search_n(testVector, 1, 22);
ASSERT_FALSE(testSubrange.empty());
EXPECT_EQ(22, testSubrange.front());
// 2 Consecutive values of 22 does not exist in vector
testSubrange = AZStd::ranges::search_n(testVector, 2, 22);
EXPECT_TRUE(testSubrange.empty());
// 2 Consecutive values of -8 does exist in vector
testSubrange = AZStd::ranges::search_n(testVector, 2,- 8);
ASSERT_EQ(2, testSubrange.size());
EXPECT_EQ(-8, testSubrange[0]);
EXPECT_EQ(-8, testSubrange[1]);
}
TEST_F(RangesAlgorithmTestFixture, RangesFindEnd_LocatesElementLastElement_Succeeds)
{
AZStd::vector testVector{ 5, 1, 22, 47, -8, -5, 1000, 687, 22, -8, -8, 1000, 45 };
AZStd::array testArray{ -8 };
auto testSubrange = AZStd::ranges::find_end(testVector, testArray);
ASSERT_FALSE(testSubrange.empty());
EXPECT_EQ(-8, testSubrange.front());
EXPECT_EQ(testVector.end() - 3, testSubrange.begin());
}
TEST_F(RangesAlgorithmTestFixture, RangesEqual_IsAbleToCompareTwoRanges_Succeeds)
{
AZStd::vector testVector{ 5, 1, 22, 47, -8, -5, 1000, 687, 22, -8, -8, 1000, 45 };
AZStd::vector longerVector{ 5, 1, 22, 47, -8, -5, 1000, 687, 22, -8, -8, 1000, 45, 929 };
AZStd::vector shorterVector{ 5, 1, 22, 47, -8, -5, 1000, 687, 22, -8, -8, 1000 };
AZStd::vector unequalVector{ 5, 1, 22, 47, -8, -5, 1000, 14, 22, -8, -8, 1000, 25 };
EXPECT_TRUE(AZStd::ranges::equal(testVector, testVector));
EXPECT_FALSE(AZStd::ranges::equal(testVector, longerVector));
EXPECT_FALSE(AZStd::ranges::equal(longerVector, testVector));
EXPECT_FALSE(AZStd::ranges::equal(testVector, shorterVector));
EXPECT_FALSE(AZStd::ranges::equal(shorterVector, testVector));
EXPECT_FALSE(AZStd::ranges::equal(testVector, unequalVector));
}
TEST_F(RangesAlgorithmTestFixture, RangesMismatch_Returns_IteratorsToMismatchElements)
{
AZStd::vector testVector{ 1, 2, 3, 4, 5 ,6 };
AZStd::vector secondVector{ 1, 2, 3, 14, 5, 6 };
AZStd::vector<int> emptyVector;
AZStd::vector<int> longerVector{ 1, 2, 3, 4, 5, 6, 7 };
{
auto [mismatchIt1, mismatchIt2] = AZStd::ranges::mismatch(testVector, secondVector);
ASSERT_NE(testVector.end(), mismatchIt1);
EXPECT_EQ(4, *mismatchIt1);
ASSERT_NE(secondVector.end(), mismatchIt2);
EXPECT_EQ(14, *mismatchIt2);
}
{
auto [mismatchIt1, mismatchIt2] = AZStd::ranges::mismatch(testVector, emptyVector);
ASSERT_NE(testVector.end(), mismatchIt1);
EXPECT_EQ(1, *mismatchIt1);
EXPECT_EQ(emptyVector.end(), mismatchIt2);
}
{
auto [mismatchIt1, mismatchIt2] = AZStd::ranges::mismatch(testVector, longerVector);
EXPECT_EQ(testVector.end(), mismatchIt1);
ASSERT_NE(longerVector.end(), mismatchIt2);
EXPECT_EQ(7, *mismatchIt2);
}
}
}

@ -0,0 +1,483 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzCore/UnitTest/TestTypes.h>
#include <AzCore/std/containers/list.h>
#include <AzCore/std/containers/map.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/ranges/all_view.h>
#include <AzCore/std/ranges/elements_view.h>
#include <AzCore/std/ranges/empty_view.h>
#include <AzCore/std/ranges/join_view.h>
#include <AzCore/std/ranges/ranges_adaptor.h>
#include <AzCore/std/ranges/single_view.h>
#include <AzCore/std/ranges/split_view.h>
#include <AzCore/std/ranges/subrange.h>
#include <AzCore/std/ranges/zip_view.h>
#include <AzCore/std/string/string_view.h>
namespace UnitTest
{
class RangesViewTestFixture
: public ScopedAllocatorSetupFixture
{};
TEST_F(RangesViewTestFixture, AllRangeAdaptor_Succeeds)
{
AZStd::string_view testString{ "Hello World" };
auto testAllView = AZStd::ranges::views::all(testString);
EXPECT_EQ(testString.size(), testAllView.size());
EXPECT_EQ(testString.data(), testAllView.data());
EXPECT_EQ(testString.begin(), testAllView.begin());
EXPECT_EQ(testString.end(), testAllView.end());
EXPECT_EQ(testString.empty(), testAllView.empty());
EXPECT_EQ(testString.front(), testAllView.front());
EXPECT_EQ(testString.back(), testAllView.back());
EXPECT_EQ(testString[5], testAllView[5]);
auto testAllViewChain = testString | AZStd::ranges::views::all;
EXPECT_EQ(testString.size(), testAllViewChain.size());
EXPECT_EQ(testString.data(), testAllViewChain.data());
EXPECT_EQ(testString.begin(), testAllViewChain.begin());
EXPECT_EQ(testString.end(), testAllViewChain.end());
EXPECT_EQ(testString.empty(), testAllViewChain.empty());
EXPECT_EQ(testString.front(), testAllViewChain.front());
EXPECT_EQ(testString.back(), testAllViewChain.back());
EXPECT_EQ(testString[5], testAllViewChain[5]);
}
TEST_F(RangesViewTestFixture, Subrange_DeductionGuides_Compile)
{
AZStd::string_view testString{ "Hello World" };
AZStd::ranges::subrange rangeDeduction(testString);
AZStd::ranges::subrange rangeDeductionWithSize(testString, testString.size());
AZStd::ranges::subrange iteratorDeduction(testString.begin(), testString.end());
AZStd::ranges::subrange iteratorDeductionWithSize(testString.begin(), testString.end(),
testString.size());
EXPECT_TRUE(rangeDeduction);
EXPECT_TRUE(rangeDeductionWithSize);
EXPECT_TRUE(iteratorDeduction);
EXPECT_TRUE(iteratorDeductionWithSize);
}
TEST_F(RangesViewTestFixture, Subrange_CanTakeSubsetOfContainer_Succeeds)
{
AZStd::vector<int> testVector{ 1, 3, 5, 6, 7, 6, 89, -178 };
AZStd::ranges::subrange subVector(testVector);
EXPECT_TRUE(subVector);
ASSERT_FALSE(subVector.empty());
EXPECT_EQ(testVector.data(), subVector.data());
EXPECT_EQ(testVector.begin(), subVector.begin());
EXPECT_EQ(testVector.end(), subVector.end());
EXPECT_EQ(testVector.size(), subVector.size());
EXPECT_EQ(testVector[0], subVector[0]);
EXPECT_EQ(testVector.front(), subVector.front());
EXPECT_EQ(testVector.back(), subVector.back());
// Now validate the iterator operations
subVector.advance(2);
subVector = subVector.prev();
subVector.advance(2);
subVector = subVector.next();
subVector.advance(-4);
EXPECT_EQ(testVector.begin(), subVector.begin());
// Obtain a copy of the subrange with the first and last elements removed
AZStd::ranges::subrange subVectorSplice(subVector.begin() + 1, subVector.end() - 1);
EXPECT_TRUE(subVectorSplice);
ASSERT_FALSE(subVector.empty());
EXPECT_LT(testVector.data(), subVectorSplice.data());
EXPECT_EQ(testVector.begin() + 1, subVectorSplice.begin());
EXPECT_EQ(testVector.end() - 1, subVectorSplice.end());
ASSERT_EQ(testVector.size() - 2, subVectorSplice.size());
EXPECT_EQ(testVector[1], subVectorSplice.front());
EXPECT_EQ(testVector[testVector.size() - 2], subVectorSplice.back());
EXPECT_NE(testVector.front(), subVectorSplice.front());
EXPECT_NE(testVector.back(), subVectorSplice.back());
}
TEST_F(RangesViewTestFixture, EmptyView_ReturnsEmptyViewRange_Succeeds)
{
AZStd::ranges::empty_view<int> emptyView;
EXPECT_EQ(nullptr, emptyView.data());
EXPECT_EQ(0, emptyView.size());
EXPECT_TRUE(emptyView.empty());
EXPECT_EQ(emptyView.end(), emptyView.begin());
EXPECT_EQ(nullptr, AZStd::ranges::views::empty<AZStd::string_view>.data());
EXPECT_EQ(0, AZStd::ranges::views::empty<AZStd::string_view>.size());
EXPECT_TRUE(AZStd::ranges::views::empty<AZStd::string_view>.empty());
EXPECT_EQ(AZStd::ranges::views::empty<AZStd::string_view>.end(), AZStd::ranges::views::empty<AZStd::string_view>.begin());
}
TEST_F(RangesViewTestFixture, SingleView_ReturnsViewOverSingleElement_Succeeds)
{
AZStd::string_view testString{ "Hello World" };
AZStd::ranges::single_view singleView{ AZStd::move(testString) };
EXPECT_NE(nullptr, singleView.data());
EXPECT_EQ(1, singleView.size());
EXPECT_FALSE(singleView.empty());
ASSERT_NE(singleView.end(), singleView.begin());
auto singleViewStringIt = singleView.begin();
EXPECT_EQ("Hello World", *singleViewStringIt);
}
TEST_F(RangesViewTestFixture, RefView_CanWrapStringView_Succeeds)
{
AZStd::string_view testString{ "Hello World" };
AZStd::ranges::ref_view refView(testString);
EXPECT_EQ(testString.size(), refView.size());
EXPECT_EQ(testString.data(), refView.data());
EXPECT_EQ(testString.begin(), refView.begin());
EXPECT_EQ(testString.end(), refView.end());
EXPECT_EQ(testString.empty(), refView.empty());
EXPECT_EQ(testString.front(), refView.front());
EXPECT_EQ(testString.back(), refView.back());
EXPECT_EQ(testString[5], refView[5]);
}
TEST_F(RangesViewTestFixture, OwningView_CanWrapStringView_Succeeds)
{
AZStd::string_view sourceView{ "Hello World" };
AZStd::string_view testString{ sourceView };
AZStd::ranges::owning_view owningView(AZStd::move(testString));
EXPECT_TRUE(testString.empty());
EXPECT_FALSE(owningView.empty());
EXPECT_EQ(sourceView.size(), owningView.size());
EXPECT_EQ(sourceView.data(), owningView.data());
EXPECT_EQ(sourceView.begin(), owningView.begin());
EXPECT_EQ(sourceView.end(), owningView.end());
EXPECT_EQ(sourceView.empty(), owningView.empty());
EXPECT_EQ(sourceView.front(), owningView.front());
EXPECT_EQ(sourceView.back(), owningView.back());
EXPECT_EQ(sourceView[5], owningView[5]);
}
MATCHER_P(ZipViewAtSentinel, sentinel, "") {
*result_listener << "zip view has iterated to sentinel";
return !(arg == sentinel);
}
TEST_F(RangesViewTestFixture, ZipView_CompilesWithRange_Succeeds)
{
AZStd::string_view sourceView{ "Hello World" };
AZStd::ranges::zip_view zipView(AZStd::move(sourceView));
auto zipItTuple = zipView.begin();
auto zipSentinelTuple = zipView.end();
ASSERT_THAT(zipItTuple, ZipViewAtSentinel(zipSentinelTuple));
EXPECT_EQ('H', AZStd::get<0>(*zipItTuple));
ptrdiff_t zipDistance = zipSentinelTuple - zipItTuple;
EXPECT_EQ(11, zipDistance);
AZStd::list<int> sourceList{ 1, 2, 3, 4, 5 };
AZStd::ranges::zip_view zipView2(AZStd::move(sourceList));
auto zipListTupleIt = zipView2.begin();
auto zipListTupleEnd = zipView2.end();
ASSERT_THAT(zipListTupleIt, ZipViewAtSentinel(zipListTupleEnd));
}
TEST_F(RangesViewTestFixture, ZipView_CanIteratOverMultipleContainers_Succeeds)
{
AZStd::string_view sourceView{ "abcdef" };
AZStd::vector intVector{ 1, 2, 3, 4, 5 };
AZStd::list<uint32_t> uintList{ 2, 4, 6, 8, 10 };
constexpr int expectedIterations = 5;
int iterationCount{};
for (auto [charX, intY, uintZ] : (AZStd::ranges::views::zip(sourceView, AZStd::move(intVector), AZStd::move(uintList))))
{
++iterationCount;
switch (charX)
{
case 'a':
EXPECT_EQ(1, intY);
EXPECT_EQ(2, uintZ);
break;
case 'b':
EXPECT_EQ(2, intY);
EXPECT_EQ(4, uintZ);
break;
case 'c':
EXPECT_EQ(3, intY);
EXPECT_EQ(6, uintZ);
break;
case 'd':
EXPECT_EQ(4, intY);
EXPECT_EQ(8, uintZ);
break;
case 'e':
EXPECT_EQ(5, intY);
EXPECT_EQ(10, uintZ);
break;
default:
ADD_FAILURE() << "Unexpected character value " << charX << " found when iterating zip view";
}
}
EXPECT_EQ(expectedIterations, iterationCount);
}
TEST_F(RangesViewTestFixture, SplitView_CanSplitPatterns_Succeeds)
{
AZStd::string_view emptyView{ "" };
auto splitView = AZStd::ranges::views::split(emptyView, " ");
auto splitIt = splitView.begin();
EXPECT_EQ(splitView.end(), splitIt);
AZStd::string_view testView1{ "Hello" };
auto splitViewCharPattern = AZStd::ranges::views::split(testView1, ' ');
auto splitCharIt = splitViewCharPattern.begin();
ASSERT_NE(splitViewCharPattern.end(), splitCharIt);
EXPECT_EQ("Hello", AZStd::string_view(*splitCharIt));
++splitCharIt;
EXPECT_EQ(splitViewCharPattern.end(), splitCharIt);
AZStd::string_view testView2{ "Hello World" };
splitViewCharPattern = AZStd::ranges::views::split(testView2, ' ');
splitCharIt = splitViewCharPattern.begin();
ASSERT_NE(splitViewCharPattern.end(), splitCharIt);
EXPECT_EQ("Hello", AZStd::string_view(*splitCharIt));
++splitCharIt;
ASSERT_NE(splitViewCharPattern.end(), splitCharIt);
EXPECT_EQ("World", AZStd::string_view(*splitCharIt));
++splitCharIt;
EXPECT_EQ(splitViewCharPattern.end(), splitCharIt);
AZStd::string_view testView3{ "Hello World Moon" };
splitViewCharPattern = AZStd::ranges::views::split(testView3, ' ');
splitCharIt = splitViewCharPattern.begin();
ASSERT_NE(splitViewCharPattern.end(), splitCharIt);
EXPECT_EQ("Hello", AZStd::string_view(*splitCharIt));
++splitCharIt;
ASSERT_NE(splitViewCharPattern.end(), splitCharIt);
EXPECT_EQ("World", AZStd::string_view(*splitCharIt));
++splitCharIt;
ASSERT_NE(splitViewCharPattern.end(), splitCharIt);
EXPECT_EQ("Moon", AZStd::string_view(*splitCharIt));
++splitCharIt;
EXPECT_EQ(splitViewCharPattern.end(), splitCharIt);
AZStd::string_view testView4{ "Hello World Moon " };
splitViewCharPattern = AZStd::ranges::views::split(testView4, ' ');
splitCharIt = splitViewCharPattern.begin();
ASSERT_NE(splitViewCharPattern.end(), splitCharIt);
EXPECT_EQ("Hello", AZStd::string_view(*splitCharIt));
++splitCharIt;
ASSERT_NE(splitViewCharPattern.end(), splitCharIt);
EXPECT_EQ("World", AZStd::string_view(*splitCharIt));
++splitCharIt;
ASSERT_NE(splitViewCharPattern.end(), splitCharIt);
EXPECT_EQ("Moon", AZStd::string_view(*splitCharIt));
++splitCharIt;
ASSERT_NE(splitViewCharPattern.end(), splitCharIt);
EXPECT_EQ("", AZStd::string_view(*splitCharIt));
++splitCharIt;
EXPECT_EQ(splitViewCharPattern.end(), splitCharIt);
AZStd::string_view testView5{ "Hello World Moon " };
splitViewCharPattern = AZStd::ranges::views::split(testView5, ' ');
splitCharIt = splitViewCharPattern.begin();
ASSERT_NE(splitViewCharPattern.end(), splitCharIt);
EXPECT_EQ("Hello", AZStd::string_view(*splitCharIt));
++splitCharIt;
ASSERT_NE(splitViewCharPattern.end(), splitCharIt);
EXPECT_EQ("World", AZStd::string_view(*splitCharIt));
++splitCharIt;
ASSERT_NE(splitViewCharPattern.end(), splitCharIt);
EXPECT_EQ("Moon", AZStd::string_view(*splitCharIt));
++splitCharIt;
ASSERT_NE(splitViewCharPattern.end(), splitCharIt);
EXPECT_EQ("", AZStd::string_view(*splitCharIt));
++splitCharIt;
ASSERT_NE(splitViewCharPattern.end(), splitCharIt);
EXPECT_EQ("", AZStd::string_view(*splitCharIt));
++splitCharIt;
EXPECT_EQ(splitViewCharPattern.end(), splitCharIt);
AZStd::string_view testView6{ "Hello World Moon" };
splitViewCharPattern = AZStd::ranges::views::split(testView6, ' ');
splitCharIt = splitViewCharPattern.begin();
ASSERT_NE(splitViewCharPattern.end(), splitCharIt);
EXPECT_EQ("Hello", AZStd::string_view(*splitCharIt));
++splitCharIt;
ASSERT_NE(splitViewCharPattern.end(), splitCharIt);
EXPECT_EQ("", AZStd::string_view(*splitCharIt));
++splitCharIt;
ASSERT_NE(splitViewCharPattern.end(), splitCharIt);
EXPECT_EQ("World", AZStd::string_view(*splitCharIt));
++splitCharIt;
ASSERT_NE(splitViewCharPattern.end(), splitCharIt);
EXPECT_EQ("Moon", AZStd::string_view(*splitCharIt));
++splitCharIt;
EXPECT_EQ(splitViewCharPattern.end(), splitCharIt);
}
TEST_F(RangesViewTestFixture, SplitView_SplitsFromNonString_Succeeds)
{
const AZStd::vector<int> testVector{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// Split the vector on 3
auto splitView = AZStd::ranges::views::split(testVector, 3);
auto splitIt = splitView.begin();
ASSERT_NE(splitView.end(), splitIt);
auto splitSubrange = *splitIt;
{
AZStd::array expectedValue{ 1, 2 };
EXPECT_TRUE(AZStd::ranges::equal(expectedValue, splitSubrange));
}
++splitIt;
ASSERT_NE(splitView.end(), splitIt);
splitSubrange = *splitIt;
{
AZStd::array expectedValue{ 4, 5, 6, 7, 8, 9, 10 };
EXPECT_TRUE(AZStd::ranges::equal(expectedValue, splitSubrange));
}
}
TEST_F(RangesViewTestFixture, JoinView_IteratesOverInnerViews_Succeeds)
{
constexpr AZStd::string_view expectedString = "HelloWorldMoonSun";
using Rope = AZStd::fixed_vector<AZStd::string_view, 32>;
Rope rope{ "Hello", "World", "Moon", "Sun" };
AZStd::fixed_string<128> accumString;
for (auto&& charElement : AZStd::ranges::join_view(rope))
{
accumString.push_back(charElement);
}
EXPECT_EQ(expectedString, accumString);
}
TEST_F(RangesViewTestFixture, JoinView_IteratesCanIterateOverSplitView_Succeeds)
{
constexpr AZStd::string_view expectedString = "HelloWorldMoonSun";
constexpr AZStd::string_view splitExpression = "Hello,World,Moon,Sun";
AZStd::fixed_string<128> accumString;
for (auto&& charElement : AZStd::ranges::views::join(AZStd::ranges::views::split(splitExpression, ',')))
{
accumString.push_back(charElement);
}
EXPECT_EQ(expectedString, accumString);
}
TEST_F(RangesViewTestFixture, JoinView_IterSwapCustomization_Succeeds)
{
AZStd::fixed_vector<AZStd::string, 8> testVector1{ "World", "Hello" };
AZStd::fixed_vector<AZStd::string, 8> testVector2{ "Value", "First" };
auto joinView1 = AZStd::ranges::views::join(testVector1);
auto joinView2 = AZStd::ranges::views::join(testVector2);
auto joinViewIter1 = joinView1.begin();
auto joinViewIter2 = joinView2.begin();
// swaps the 'W' and 'V'
AZStd::ranges::iter_swap(joinViewIter1, joinViewIter2);
AZStd::ranges::advance(joinViewIter1, 5, joinView1.end());
AZStd::ranges::advance(joinViewIter2, 5, joinView2.end());
// swaps the 'H' and 'F' of the second string of each vector
AZStd::ranges::iter_swap(joinViewIter1, joinViewIter2);
EXPECT_EQ("Vorld", testVector1[0]);
EXPECT_EQ("Fello", testVector1[1]);
EXPECT_EQ("Walue", testVector2[0]);
EXPECT_EQ("Hirst", testVector2[1]);
}
TEST_F(RangesViewTestFixture, JoinView_IterMoveCustomization_Succeeds)
{
using StringWrapper = AZStd::ranges::single_view<AZStd::string>;
AZStd::fixed_vector<StringWrapper, 8> testVector1{ StringWrapper{"5"}, StringWrapper{"10"} };
AZStd::fixed_vector<StringWrapper, 8> testVector2{ StringWrapper{"15"}, StringWrapper{"20"} };
auto joinView1 = AZStd::ranges::views::join(testVector1);
auto joinView2 = AZStd::ranges::views::join(testVector2);
auto joinViewIter1 = joinView1.begin();
auto joinViewIter2 = joinView2.begin();
AZStd::string value = AZStd::ranges::iter_move(joinViewIter1);
EXPECT_EQ("5", value);
EXPECT_TRUE((*joinViewIter1).empty());
++joinViewIter2;
value = AZStd::ranges::iter_move(joinViewIter2);
EXPECT_EQ("20", value);
EXPECT_TRUE((*joinViewIter2).empty());
}
TEST_F(RangesViewTestFixture, ElementsView_CanIterateVectorOfTuple_Succeeds)
{
using TestTuple = AZStd::tuple<int, AZStd::string, bool>;
AZStd::vector testVector{ TestTuple{1, "hello", false}, TestTuple{2, "world", true},
TestTuple{3, "Moon", false} };
auto firstElementView = AZStd::ranges::views::elements<0>(testVector);
auto firstElementBegin = AZStd::ranges::begin(firstElementView);
auto firstElementEnd = AZStd::ranges::end(firstElementView);
EXPECT_NE(firstElementEnd, firstElementBegin);
ASSERT_EQ(3, firstElementView.size());
EXPECT_EQ(1, firstElementView[0]);
EXPECT_EQ(2, firstElementView[1]);
EXPECT_EQ(3, firstElementView[2]);
auto secondElementView = AZStd::ranges::views::elements<1>(testVector);
ASSERT_EQ(3, secondElementView.size());
EXPECT_EQ("hello", secondElementView[0]);
EXPECT_EQ("world", secondElementView[1]);
EXPECT_EQ("Moon", secondElementView[2]);
auto thirdElementView = AZStd::ranges::views::elements<2>(testVector);
ASSERT_EQ(3, thirdElementView.size());
EXPECT_FALSE(thirdElementView[0]);
EXPECT_TRUE(thirdElementView[1]);
EXPECT_FALSE(thirdElementView[2]);
using TestPair = AZStd::pair<AZStd::string, int>;
AZStd::vector testPairVector{ TestPair{"hello", 5}, TestPair{"world", 10}, TestPair{"Sun", 15} };
using ElementsViewBase = AZStd::ranges::views::all_t<decltype((testPairVector))>;
using ElementsViewType = AZStd::ranges::elements_view<ElementsViewBase, 0>;
constexpr AZStd::string_view expectedString = "helloworldSun";
AZStd::string accumString;
for (auto&& stringValue : ElementsViewType(testPairVector))
{
accumString += stringValue;
}
EXPECT_EQ(expectedString, accumString);
}
TEST_F(RangesViewTestFixture, ElementsView_KeysAlias_CanIterateAssociativeContainerKeyType)
{
using PairType = AZStd::pair<int, const char*>;
AZStd::map testMap{ PairType{1, "Hello"}, PairType{2, "World"}, PairType{3, "Sun"}, PairType{45, "RandomText"} };
int accumResult{};
for (int key : AZStd::ranges::views::keys(testMap))
{
accumResult += key;
}
EXPECT_EQ(51, accumResult);
}
TEST_F(RangesViewTestFixture, ElementsView_ValuesAlias_CanIterateAssociativeContainerMappedType)
{
using PairType = AZStd::pair<int, const char*>;
AZStd::map testMap{ PairType{1, "Hello"}, PairType{2, "World"}, PairType{3, "Sun"}, PairType{45, "RandomText"} };
AZStd::string accumResult{};
for (const char* value : AZStd::ranges::views::values(testMap))
{
accumResult += value;
}
EXPECT_EQ("HelloWorldSunRandomText", accumResult);
}
}

@ -2537,7 +2537,7 @@ namespace Benchmark
{
AZStd::string test1{ "foo bar"};
AZStd::string test2{ "bar foo" };
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
SwapStringViaPointerSizedSwaps(test1, test2);
}
@ -2547,7 +2547,7 @@ namespace Benchmark
{
AZStd::string test1{ "The brown quick wolf jumped over the hyperactive cat" };
AZStd::string test2{ "The quick brown fox jumped over the lazy dog" };
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
SwapStringViaPointerSizedSwaps(test1, test2);
}
@ -2557,7 +2557,7 @@ namespace Benchmark
{
AZStd::string test1{ "foo bar" };
AZStd::string test2{ "bar foo" };
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
SwapStringViaMemcpy(test1, test2);
}
@ -2567,7 +2567,7 @@ namespace Benchmark
{
AZStd::string test1{ "The brown quick wolf jumped over the hyperactive cat" };
AZStd::string test2{ "The quick brown fox jumped over the lazy dog" };
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
SwapStringViaMemcpy(test1, test2);
}
@ -2584,7 +2584,7 @@ namespace Benchmark
AZStd::string sourceString(state.range(0), 'a');
const char* sourceAddress = sourceString.c_str();
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
AZStd::string assignString;
assignString.assign(sourceAddress);
@ -2600,7 +2600,7 @@ namespace Benchmark
const char* sourceAddress = sourceString.c_str();
const size_t sourceSize = sourceString.size();
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
AZStd::string assignString;
assignString.assign(sourceAddress, sourceSize);
@ -2616,7 +2616,7 @@ namespace Benchmark
auto sourceBegin = sourceString.begin();
auto sourceEnd = sourceString.end();
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
AZStd::string assignString;
assignString.assign(sourceBegin, sourceEnd);
@ -2631,7 +2631,7 @@ namespace Benchmark
AZStd::string sourceString(state.range(0), 'a');
AZStd::string_view sourceView(sourceString);
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
AZStd::string assignString;
assignString.assign(sourceView);
@ -2645,7 +2645,7 @@ namespace Benchmark
{
AZStd::string sourceString(state.range(0), 'a');
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
AZStd::string assignString;
assignString.assign(sourceString);
@ -2659,7 +2659,7 @@ namespace Benchmark
{
AZStd::string sourceString(state.range(0), 'a');
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
AZStd::string assignString;
assignString.assign(AZStd::move(sourceString));
@ -2671,7 +2671,7 @@ namespace Benchmark
BENCHMARK_TEMPLATE_DEFINE_F(StringTemplateBenchmarkFixture, BM_StringAssignFromSingleCharacter, AZStd::string)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
AZStd::string assignString;
assignString.assign(state.range(0), 'a');
@ -2689,7 +2689,7 @@ namespace Benchmark
AZStd::fixed_string<1024> sourceString(state.range(0), 'a');
const char* sourceAddress = sourceString.c_str();
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
AZStd::fixed_string<1024> assignString;
assignString.assign(sourceAddress);
@ -2705,7 +2705,7 @@ namespace Benchmark
const char* sourceAddress = sourceString.c_str();
const size_t sourceSize = sourceString.size();
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
AZStd::fixed_string<1024> assignString;
assignString.assign(sourceAddress, sourceSize);
@ -2721,7 +2721,7 @@ namespace Benchmark
auto sourceBegin = sourceString.begin();
auto sourceEnd = sourceString.end();
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
AZStd::fixed_string<1024> assignString;
assignString.assign(sourceBegin, sourceEnd);
@ -2736,7 +2736,7 @@ namespace Benchmark
AZStd::fixed_string<1024> sourceString(state.range(0), 'a');
AZStd::string_view sourceView(sourceString);
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
AZStd::fixed_string<1024> assignString;
assignString.assign(sourceView);
@ -2750,7 +2750,7 @@ namespace Benchmark
{
AZStd::fixed_string<1024> sourceString(state.range(0), 'a');
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
AZStd::fixed_string<1024> assignString;
assignString.assign(sourceString);
@ -2764,7 +2764,7 @@ namespace Benchmark
{
AZStd::fixed_string<1024> sourceString(state.range(0), 'a');
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
AZStd::fixed_string<1024> assignString;
assignString.assign(AZStd::move(sourceString));
@ -2776,7 +2776,7 @@ namespace Benchmark
BENCHMARK_TEMPLATE_DEFINE_F(StringTemplateBenchmarkFixture, BM_FixedStringAssignFromSingleCharacter, AZStd::fixed_string<1024>)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
AZStd::fixed_string<1024> assignString;
assignString.assign(state.range(0), 'a');

@ -29,7 +29,7 @@ namespace AZ::Dom::Benchmark
AZ::Dom::JsonBackend backend;
AZStd::string serializedPayload = GenerateDomJsonBenchmarkPayload(state.range(0), state.range(1));
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
state.PauseTiming();
AZStd::string payloadCopy = serializedPayload;
@ -53,7 +53,7 @@ namespace AZ::Dom::Benchmark
AZ::Dom::JsonBackend backend;
AZStd::string serializedPayload = GenerateDomJsonBenchmarkPayload(state.range(0), state.range(1));
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
state.PauseTiming();
AZStd::string payloadCopy = serializedPayload;
@ -77,7 +77,7 @@ namespace AZ::Dom::Benchmark
AZ::Dom::JsonBackend backend;
AZStd::string serializedPayload = GenerateDomJsonBenchmarkPayload(state.range(0), state.range(1));
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
auto result = AZ::Dom::Json::WriteToRapidJsonDocument(
[&](AZ::Dom::Visitor& visitor)
@ -97,7 +97,7 @@ namespace AZ::Dom::Benchmark
AZ::Dom::JsonBackend backend;
AZStd::string serializedPayload = GenerateDomJsonBenchmarkPayload(state.range(0), state.range(1));
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
auto result = AZ::Dom::Utils::WriteToValue(
[&](AZ::Dom::Visitor& visitor)
@ -117,7 +117,7 @@ namespace AZ::Dom::Benchmark
AZ::Dom::JsonBackend backend;
AZStd::string serializedPayload = GenerateDomJsonBenchmarkPayload(state.range(0), state.range(1));
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
auto result = AZ::JsonSerializationUtils::ReadJsonString(serializedPayload);
@ -130,7 +130,7 @@ namespace AZ::Dom::Benchmark
BENCHMARK_DEFINE_F(DomJsonBenchmark, RapidjsonMakeComplexObject)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
TakeAndDiscardWithoutTimingDtor(GenerateDomJsonBenchmarkPayload(state.range(0), state.range(1)), state);
}
@ -152,7 +152,7 @@ namespace AZ::Dom::Benchmark
document.GetAllocator());
}
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (const AZStd::string& key : keys)
{
@ -168,7 +168,7 @@ namespace AZ::Dom::Benchmark
{
rapidjson::Document original = GenerateDomJsonBenchmarkDocument(state.range(0), state.range(1));
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
rapidjson::Document copy;
copy.CopyFrom(original, copy.GetAllocator(), true);
@ -184,7 +184,7 @@ namespace AZ::Dom::Benchmark
{
rapidjson::Document original = GenerateDomJsonBenchmarkDocument(state.range(0), state.range(1));
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
rapidjson::Document copy;
copy.CopyFrom(original, copy.GetAllocator(), true);

@ -78,7 +78,7 @@ namespace AZ::Dom::Benchmark
if (apply)
{
auto patchInfo = GenerateHierarchicalDeltaPatch(m_before, m_after);
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
auto patchResult = patchInfo.m_forwardPatches.Apply(m_before);
benchmark::DoNotOptimize(patchResult);
@ -86,7 +86,7 @@ namespace AZ::Dom::Benchmark
}
else
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
auto patchInfo = GenerateHierarchicalDeltaPatch(m_before, m_after);
benchmark::DoNotOptimize(patchInfo);

@ -20,7 +20,7 @@ namespace AZ::Dom::Benchmark
PathEntry end;
end.SetEndOfArray();
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
Path p;
p /= entry1;
@ -40,7 +40,7 @@ namespace AZ::Dom::Benchmark
PathEntry end;
end.SetEndOfArray();
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
Path p = Path() / entry1 / entry2 / 0 / end;
}
@ -55,7 +55,7 @@ namespace AZ::Dom::Benchmark
AZStd::string s;
s.resize_no_construct(p.GetStringLength());
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
p.GetStringLength();
p.FormatString(s.data(), s.size());
@ -69,7 +69,7 @@ namespace AZ::Dom::Benchmark
{
AZStd::string pathString = "/path/with/multiple/0/different/components/including-long-strings-like-this/65536/999/-";
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
Path p(pathString);
benchmark::DoNotOptimize(p);
@ -86,7 +86,7 @@ namespace AZ::Dom::Benchmark
PathEntry endOfArray;
endOfArray.SetEndOfArray();
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
name.IsEndOfArray();
index.IsEndOfArray();
@ -104,7 +104,7 @@ namespace AZ::Dom::Benchmark
PathEntry endOfArray;
endOfArray.SetEndOfArray();
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
benchmark::DoNotOptimize(name == name);
benchmark::DoNotOptimize(name == index);

@ -29,7 +29,7 @@ namespace AZ::Dom::Benchmark
Value doubleValue(4.0);
Value stringValue("foo", true);
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
(intValue.GetType());
(boolValue.GetType());
@ -118,7 +118,7 @@ namespace AZ::Dom::Benchmark
value.GetInternalValue());
};
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
(getTypeViaVisit(intValue));
(getTypeViaVisit(boolValue));
@ -136,7 +136,7 @@ namespace AZ::Dom::Benchmark
BENCHMARK_DEFINE_F(DomValueBenchmark, AzDomValueMakeComplexObject)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
TakeAndDiscardWithoutTimingDtor(GenerateDomBenchmarkPayload(state.range(0), state.range(1)), state);
}
@ -149,7 +149,7 @@ namespace AZ::Dom::Benchmark
{
Value original = GenerateDomBenchmarkPayload(state.range(0), state.range(1));
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
Value copy = original;
benchmark::DoNotOptimize(copy);
@ -163,7 +163,7 @@ namespace AZ::Dom::Benchmark
{
Value original = GenerateDomBenchmarkPayload(state.range(0), state.range(1));
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
Value copy = original;
copy["entries"]["Key0"].ArrayPushBack(Value(42));
@ -178,7 +178,7 @@ namespace AZ::Dom::Benchmark
{
Value original = GenerateDomBenchmarkPayload(state.range(0), state.range(1));
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
Value copy = Utils::DeepCopy(original);
TakeAndDiscardWithoutTimingDtor(AZStd::move(copy), state);
@ -199,7 +199,7 @@ namespace AZ::Dom::Benchmark
value[key] = i;
}
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (const AZ::Name& key : keys)
{
@ -222,7 +222,7 @@ namespace AZ::Dom::Benchmark
value[key] = i;
}
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (const AZStd::string& key : keys)
{
@ -245,7 +245,7 @@ namespace AZ::Dom::Benchmark
value[key] = i;
}
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (const AZStd::string& key : keys)
{

@ -966,7 +966,7 @@ namespace Benchmark
BENCHMARK_F(PathBenchmarkFixture, BM_PathAppendFixedPath)(benchmark::State& state)
{
AZ::IO::FixedMaxPath m_testPath{ "." };
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (const auto& appendPath : m_appendPaths)
{
@ -977,7 +977,7 @@ namespace Benchmark
BENCHMARK_F(PathBenchmarkFixture, BM_PathAppendAllocatingPath)(benchmark::State& state)
{
AZ::IO::Path m_testPath{ "." };
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (const auto& appendPath : m_appendPaths)
{
@ -989,7 +989,7 @@ namespace Benchmark
BENCHMARK_F(PathBenchmarkFixture, BM_StringFuncPathJoinFixedString)(benchmark::State& state)
{
AZStd::string m_testPath{ "." };
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (const auto& appendPath : m_appendPaths)
{
@ -1000,7 +1000,7 @@ namespace Benchmark
BENCHMARK_F(PathBenchmarkFixture, BM_StringFuncPathJoinAZStdString)(benchmark::State& state)
{
AZStd::string m_testPath{ "." };
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (const auto& appendPath : m_appendPaths)
{

@ -1741,7 +1741,7 @@ namespace Benchmark
BENCHMARK_F(JobBenchmarkFixture, RunSmallNumberOfLightWeightJobsWithDefaultPriority)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
RunMultipleCalculatePiJobsWithDefaultPriority(SMALL_NUMBER_OF_JOBS, LIGHT_WEIGHT_JOB_CALCULATE_PI_DEPTH);
}
@ -1749,7 +1749,7 @@ namespace Benchmark
BENCHMARK_F(JobBenchmarkFixture, RunMediumNumberOfLightWeightJobsWithDefaultPriority)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
RunMultipleCalculatePiJobsWithDefaultPriority(MEDIUM_NUMBER_OF_JOBS, LIGHT_WEIGHT_JOB_CALCULATE_PI_DEPTH);
}
@ -1757,7 +1757,7 @@ namespace Benchmark
BENCHMARK_F(JobBenchmarkFixture, RunLargeNumberOfLightWeightJobsWithDefaultPriority)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
RunMultipleCalculatePiJobsWithDefaultPriority(LARGE_NUMBER_OF_JOBS, LIGHT_WEIGHT_JOB_CALCULATE_PI_DEPTH);
}
@ -1765,7 +1765,7 @@ namespace Benchmark
BENCHMARK_F(JobBenchmarkFixture, RunSmallNumberOfMediumWeightJobsWithDefaultPriority)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
RunMultipleCalculatePiJobsWithDefaultPriority(SMALL_NUMBER_OF_JOBS, MEDIUM_WEIGHT_JOB_CALCULATE_PI_DEPTH);
}
@ -1773,7 +1773,7 @@ namespace Benchmark
BENCHMARK_F(JobBenchmarkFixture, RunMediumNumberOfMediumWeightJobsWithDefaultPriority)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
RunMultipleCalculatePiJobsWithDefaultPriority(MEDIUM_NUMBER_OF_JOBS, MEDIUM_WEIGHT_JOB_CALCULATE_PI_DEPTH);
}
@ -1781,7 +1781,7 @@ namespace Benchmark
BENCHMARK_F(JobBenchmarkFixture, RunLargeNumberOfMediumWeightJobsWithDefaultPriority)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
RunMultipleCalculatePiJobsWithDefaultPriority(LARGE_NUMBER_OF_JOBS, MEDIUM_WEIGHT_JOB_CALCULATE_PI_DEPTH);
}
@ -1789,7 +1789,7 @@ namespace Benchmark
BENCHMARK_F(JobBenchmarkFixture, RunSmallNumberOfHeavyWeightJobsWithDefaultPriority)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
RunMultipleCalculatePiJobsWithDefaultPriority(SMALL_NUMBER_OF_JOBS, HEAVY_WEIGHT_JOB_CALCULATE_PI_DEPTH);
}
@ -1797,7 +1797,7 @@ namespace Benchmark
BENCHMARK_F(JobBenchmarkFixture, RunMediumNumberOfHeavyWeightJobsWithDefaultPriority)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
RunMultipleCalculatePiJobsWithDefaultPriority(MEDIUM_NUMBER_OF_JOBS, HEAVY_WEIGHT_JOB_CALCULATE_PI_DEPTH);
}
@ -1805,7 +1805,7 @@ namespace Benchmark
BENCHMARK_F(JobBenchmarkFixture, RunLargeNumberOfHeavyWeightJobsWithDefaultPriority)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
RunMultipleCalculatePiJobsWithDefaultPriority(LARGE_NUMBER_OF_JOBS, HEAVY_WEIGHT_JOB_CALCULATE_PI_DEPTH);
}
@ -1813,7 +1813,7 @@ namespace Benchmark
BENCHMARK_F(JobBenchmarkFixture, RunSmallNumberOfRandomWeightJobsWithDefaultPriority)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
RunMultipleCalculatePiJobsWithRandomDepthAndDefaultPriority(SMALL_NUMBER_OF_JOBS);
}
@ -1821,7 +1821,7 @@ namespace Benchmark
BENCHMARK_F(JobBenchmarkFixture, RunMediumNumberOfRandomWeightJobsWithDefaultPriority)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
RunMultipleCalculatePiJobsWithRandomDepthAndDefaultPriority(MEDIUM_NUMBER_OF_JOBS);
}
@ -1829,7 +1829,7 @@ namespace Benchmark
BENCHMARK_F(JobBenchmarkFixture, RunLargeNumberOfRandomWeightJobsWithDefaultPriority)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
RunMultipleCalculatePiJobsWithRandomDepthAndDefaultPriority(LARGE_NUMBER_OF_JOBS);
}
@ -1837,7 +1837,7 @@ namespace Benchmark
BENCHMARK_F(JobBenchmarkFixture, RunSmallNumberOfLightWeightJobsWithRandomPriorities)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
RunMultipleCalculatePiJobsWithRandomPriority(SMALL_NUMBER_OF_JOBS, LIGHT_WEIGHT_JOB_CALCULATE_PI_DEPTH);
}
@ -1845,7 +1845,7 @@ namespace Benchmark
BENCHMARK_F(JobBenchmarkFixture, RunMediumNumberOfLightWeightJobsWithRandomPriorities)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
RunMultipleCalculatePiJobsWithRandomPriority(MEDIUM_NUMBER_OF_JOBS, LIGHT_WEIGHT_JOB_CALCULATE_PI_DEPTH);
}
@ -1853,7 +1853,7 @@ namespace Benchmark
BENCHMARK_F(JobBenchmarkFixture, RunLargeNumberOfLightWeightJobsWithRandomPriorities)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
RunMultipleCalculatePiJobsWithRandomPriority(LARGE_NUMBER_OF_JOBS, LIGHT_WEIGHT_JOB_CALCULATE_PI_DEPTH);
}
@ -1861,7 +1861,7 @@ namespace Benchmark
BENCHMARK_F(JobBenchmarkFixture, RunSmallNumberOfMediumWeightJobsWithRandomPriorities)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
RunMultipleCalculatePiJobsWithRandomPriority(SMALL_NUMBER_OF_JOBS, MEDIUM_WEIGHT_JOB_CALCULATE_PI_DEPTH);
}
@ -1869,7 +1869,7 @@ namespace Benchmark
BENCHMARK_F(JobBenchmarkFixture, RunMediumNumberOfMediumWeightJobsWithRandomPriorities)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
RunMultipleCalculatePiJobsWithRandomPriority(MEDIUM_NUMBER_OF_JOBS, MEDIUM_WEIGHT_JOB_CALCULATE_PI_DEPTH);
}
@ -1877,7 +1877,7 @@ namespace Benchmark
BENCHMARK_F(JobBenchmarkFixture, RunLargeNumberOfMediumWeightJobsWithRandomPriorities)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
RunMultipleCalculatePiJobsWithRandomPriority(LARGE_NUMBER_OF_JOBS, MEDIUM_WEIGHT_JOB_CALCULATE_PI_DEPTH);
}
@ -1885,7 +1885,7 @@ namespace Benchmark
BENCHMARK_F(JobBenchmarkFixture, RunSmallNumberOfHeavyWeightJobsWithRandomPriorities)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
RunMultipleCalculatePiJobsWithRandomPriority(SMALL_NUMBER_OF_JOBS, HEAVY_WEIGHT_JOB_CALCULATE_PI_DEPTH);
}
@ -1893,7 +1893,7 @@ namespace Benchmark
BENCHMARK_F(JobBenchmarkFixture, RunMediumNumberOfHeavyWeightJobsWithRandomPriorities)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
RunMultipleCalculatePiJobsWithRandomPriority(MEDIUM_NUMBER_OF_JOBS, HEAVY_WEIGHT_JOB_CALCULATE_PI_DEPTH);
}
@ -1901,7 +1901,7 @@ namespace Benchmark
BENCHMARK_F(JobBenchmarkFixture, RunLargeNumberOfHeavyWeightJobsWithRandomPriorities)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
RunMultipleCalculatePiJobsWithRandomPriority(LARGE_NUMBER_OF_JOBS, HEAVY_WEIGHT_JOB_CALCULATE_PI_DEPTH);
}
@ -1909,7 +1909,7 @@ namespace Benchmark
BENCHMARK_F(JobBenchmarkFixture, RunSmallNumberOfRandomWeightJobsWithRandomPriorities)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
RunMultipleCalculatePiJobsWithRandomDepthAndRandomPriority(SMALL_NUMBER_OF_JOBS);
}
@ -1917,7 +1917,7 @@ namespace Benchmark
BENCHMARK_F(JobBenchmarkFixture, RunMediumNumberOfRandomWeightJobsWithRandomPriorities)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
RunMultipleCalculatePiJobsWithRandomDepthAndRandomPriority(MEDIUM_NUMBER_OF_JOBS);
}
@ -1925,7 +1925,7 @@ namespace Benchmark
BENCHMARK_F(JobBenchmarkFixture, RunLargeNumberOfRandomWeightJobsWithRandomPriorities)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
RunMultipleCalculatePiJobsWithRandomDepthAndRandomPriority(LARGE_NUMBER_OF_JOBS);
}

@ -7,28 +7,13 @@
*/
#include <AzCore/UnitTest/UnitTest.h>
#include <AzCore/UnitTest/TestTypes.h>
#include <AzTest/AzTest.h>
#if defined(HAVE_BENCHMARK)
namespace AzCore
{
class AzCoreBenchmarkEnvironment
: public AZ::Test::BenchmarkEnvironmentBase
{
void SetUpBenchmark() override
{
AZ::AllocatorInstance<AZ::SystemAllocator>::Create();
}
void TearDownBenchmark() override
{
AZ::AllocatorInstance<AZ::SystemAllocator>::Destroy();
}
};
}
AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV, AzCore::AzCoreBenchmarkEnvironment)
AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV, UnitTest::ScopedAllocatorBenchmarkEnvironment)
#else

@ -54,7 +54,7 @@ namespace Benchmark
{
// Runtime performance is not actually being measured by this test.
// This function only exist to calculate AZ::Crc32 values at compile time
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
[[maybe_unused]] constexpr auto resultArray = Crc32Internal::GenerateTestCrc32Values();
}

@ -63,7 +63,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathFrustum, SphereIntersect)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& data : m_dataArray)
{
@ -75,7 +75,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathFrustum, AabbIntersect)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& data : m_dataArray)
{

@ -68,7 +68,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, CreateIdentity)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for ([[maybe_unused]] auto& testData : m_testDataArray)
{
@ -80,7 +80,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, CreateZero)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for ([[maybe_unused]] auto& testData : m_testDataArray)
{
@ -92,7 +92,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, GetRowX3)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -108,7 +108,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, GetColumnX3)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -124,7 +124,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, CreateFromValue)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -136,7 +136,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, CreateFromRowMajorFloat9)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for ([[maybe_unused]] auto& testData : m_testDataArray)
{
@ -148,7 +148,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, CreateFromColumnMajorFloat9)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for ([[maybe_unused]] auto& testData : m_testDataArray)
{
@ -162,7 +162,7 @@ namespace Benchmark
{
float storeValues[9];
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -176,7 +176,7 @@ namespace Benchmark
{
float storeValues[9];
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -188,7 +188,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, CreateRotationX)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -200,7 +200,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, CreateRotationY)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -212,7 +212,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, CreateRotationZ)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -224,7 +224,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, CreateFromTransform)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -236,7 +236,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, CreateFromMatrix4x4)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -248,7 +248,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, CreateFromQuaternion)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -260,7 +260,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, CreateScale)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -272,7 +272,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, CreateDiagonal)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -284,7 +284,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, CreateCrossProduct)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -296,7 +296,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, GetElement)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -308,7 +308,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, SetElement)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -321,7 +321,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, SetRowX3)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -336,7 +336,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, SetColumnX3)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -351,7 +351,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, GetBasisX)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -363,7 +363,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, GetBasisY)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -375,7 +375,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, GetBasisZ)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -387,7 +387,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, OperatorAssign)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -399,7 +399,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, OperatorMultiply)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -411,7 +411,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, TransposedMultiply)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -423,7 +423,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, MultiplyVector)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -435,7 +435,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, OperatorSum)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -447,7 +447,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, OperatorDifference)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -459,7 +459,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, OperatorMultiplyScalar)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -471,7 +471,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, OperatorDivideScalar)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -483,7 +483,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, Transpose)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -494,7 +494,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, GetTranspose)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -506,7 +506,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, RetrieveScale)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -518,7 +518,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, ExtractScale)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -530,7 +530,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, MultiplyByScaleX2)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -542,7 +542,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, GetPolarDecomposition)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -557,7 +557,7 @@ namespace Benchmark
AZ::Matrix3x3 orthogonalOut;
AZ::Matrix3x3 symmetricOut;
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -568,7 +568,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, GetInverseFast)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -580,7 +580,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, GetInverseFull)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -592,7 +592,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, Orthogonalize)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -603,7 +603,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, GetOrthogonalized)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -615,7 +615,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, IsOrthogonal)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -627,7 +627,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, GetDiagonal)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -639,7 +639,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, GetDeterminant)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -651,7 +651,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x3, GetAdjugate)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{

@ -86,7 +86,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, CreateIdentity)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for ([[maybe_unused]] auto& testData : m_testDataArray)
{
@ -98,7 +98,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, CreateZero)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for ([[maybe_unused]] auto& testData : m_testDataArray)
{
@ -110,7 +110,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, CreateFromValue)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -122,7 +122,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, CreateFromRowMajorFloat12)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -134,7 +134,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, CreateFromRows)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -146,7 +146,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, CreateFromColumnMajorFloat12)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -158,7 +158,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, CreateFromColumns)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -170,7 +170,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, CreateFromColumnMajorFloat16)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -182,7 +182,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, CreateRotationX)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -194,7 +194,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, CreateRotationY)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -206,7 +206,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, CreateRotationZ)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -218,7 +218,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, CreateFromQuaternion)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -230,7 +230,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, CreateFromQuaternionAndTranslation)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -242,7 +242,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, CreateFromMatrix3x3)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -254,7 +254,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, CreateFromMatrix3x3AndTranslation)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -266,7 +266,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, CreateFromTransform)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -278,7 +278,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, CreateScale)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -290,7 +290,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, CreateFromTranslation)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -302,7 +302,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, CreateLookAt)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -316,7 +316,7 @@ namespace Benchmark
{
float testFloats[12];
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -330,7 +330,7 @@ namespace Benchmark
{
float testFloats[12];
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -344,7 +344,7 @@ namespace Benchmark
{
float testFloats[16];
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -356,7 +356,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, GetElement)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -368,7 +368,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, SetElement)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -381,7 +381,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, GetRow)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -393,7 +393,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, GetRowAsVector3)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -405,7 +405,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, SetRowWithFloats)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -418,7 +418,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, SetRowWithVector3AndFloat)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -431,7 +431,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, SetRowWithVector4)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -444,7 +444,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, GetRows)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -459,7 +459,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, SetRows)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -472,7 +472,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, GetColumn)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -484,7 +484,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, SetColumnWithFloats)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -497,7 +497,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, SetColumnWithVector3)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -510,7 +510,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, GetColumns)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -526,7 +526,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, SetColumns)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -539,7 +539,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, GetBasisX)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -551,7 +551,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, SetBasisXWithFloats)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -564,7 +564,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, SetBasisXWithVector3)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -577,7 +577,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, GetBasisY)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -589,7 +589,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, SetBasisYWithFloats)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -602,7 +602,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, SetBasisYWithVector3)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -615,7 +615,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, GetBasisZ)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -627,7 +627,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, SetBasisZWithFloats)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -640,7 +640,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, SetBasisZWithVector3)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -653,7 +653,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, GetTranslation)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -665,7 +665,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, SetTranslationWithFloats)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -678,7 +678,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, SetTranslationWithVector3)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -691,7 +691,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, GetBasisAndTranslation)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -707,7 +707,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, SetBasisAndTranslation)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -720,7 +720,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, OperatorMultiplyMatrix3x4)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -732,7 +732,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, OperatorMultiplyEqualsMatrix3x4)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -745,7 +745,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, TransformPointVector3)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -757,7 +757,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, TransformVectorVector4)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -769,7 +769,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, Multiply3x3)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -781,7 +781,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, GetTranspose)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -793,7 +793,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, Transpose)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -806,7 +806,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, GetTranspose3x3)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -818,7 +818,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, Transpose3x3)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -831,7 +831,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, GetInverseFull)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -843,7 +843,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, InvertFull)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -856,7 +856,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, GetInverseFast)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -868,7 +868,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, InvertFast)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -881,7 +881,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, RetrieveScale)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -893,7 +893,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, ExtractScale)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -906,7 +906,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, MultiplyByScale)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -919,7 +919,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, IsOrthogonal)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -931,7 +931,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, GetOrthogonalized)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -943,7 +943,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, Orthogonalize)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -956,7 +956,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, IsCloseExactAndDifferent)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -971,7 +971,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, OperatorEqualEqual)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -983,7 +983,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, OperatorNotEqual)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -995,7 +995,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, GetEulerDegrees)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -1007,7 +1007,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, GetEulerRadians)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -1019,7 +1019,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, SetFromEulerDegrees)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -1032,7 +1032,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, SetFromEulerRadians)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -1045,7 +1045,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, SetRotationPartFromQuaternion)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -1058,7 +1058,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, GetDeterminant3x3)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -1070,7 +1070,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix3x4, IsFinite)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{

@ -64,7 +64,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, CreateIdentity)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for ([[maybe_unused]] auto& testData : m_testDataArray)
{
@ -76,7 +76,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, CreateZero)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for ([[maybe_unused]] auto& testData : m_testDataArray)
{
@ -88,7 +88,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, GetRowX4)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -106,7 +106,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, GetColumnX3)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -124,7 +124,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, CreateFromValue)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for ([[maybe_unused]] auto& testData : m_testDataArray)
{
@ -136,7 +136,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, CreateFromRowMajorFloat16)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for ([[maybe_unused]] auto& testData : m_testDataArray)
{
@ -148,7 +148,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, CreateFromColumnMajorFloat9)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for ([[maybe_unused]] auto& testData : m_testDataArray)
{
@ -160,7 +160,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, CreateProjection)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for ([[maybe_unused]] auto& testData : m_testDataArray)
{
@ -172,7 +172,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, CreateProjectionFov)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for ([[maybe_unused]] auto& testData : m_testDataArray)
{
@ -184,7 +184,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, CreateInterpolated)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -198,7 +198,7 @@ namespace Benchmark
{
float storeValues[16];
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -212,7 +212,7 @@ namespace Benchmark
{
float storeValues[16];
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -224,7 +224,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, CreateRotationX)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -236,7 +236,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, CreateRotationY)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -248,7 +248,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, CreateRotationZ)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -260,7 +260,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, CreateFromQuaternion)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -272,7 +272,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, CreateScale)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -284,7 +284,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, CreateDiagonal)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -296,7 +296,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, GetElement)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -308,7 +308,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, SetElement)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -321,7 +321,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, SetRowX3)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -337,7 +337,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, SetColumnX3)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -353,7 +353,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, GetBasisX)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -365,7 +365,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, GetBasisY)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -377,7 +377,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, GetBasisZ)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -389,7 +389,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, CreateTranslation)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -401,7 +401,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, SetTranslation)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -414,7 +414,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, GetTranslation)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -426,7 +426,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, OperatorAssign)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -438,7 +438,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, OperatorMultiply)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -450,7 +450,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, OperatorMultiplyAssign)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -463,7 +463,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, OperatorMultiplyVector3)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -475,7 +475,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, OperatorMultiplyVector4)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -487,7 +487,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, TransposedMultiply3x3)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -499,7 +499,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, Multiply3x3)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -511,7 +511,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, Transpose)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -524,7 +524,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, GetTranspose)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -536,7 +536,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, GetInverseFast)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -552,7 +552,7 @@ namespace Benchmark
AZ::Matrix4x4 mat = AZ::Matrix4x4::CreateRotationX(1.0f);
mat.SetElement(0, 1, 23.1234f);
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for ([[maybe_unused]] auto& testData : m_testDataArray)
{
@ -564,7 +564,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, GetInverseFull)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -576,7 +576,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathMatrix4x4, SetRotationPartFromQuaternion)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{

@ -47,7 +47,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathObb, CreateFromPositionRotationAndHalfLengths)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < numIters; ++i)
{
@ -60,7 +60,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathObb, SetPosition)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < numIters; ++i)
{
@ -72,7 +72,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathObb, GetPosition)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < numIters; ++i)
{
@ -84,7 +84,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathObb, GetAxisX)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < numIters; ++i)
{
@ -96,7 +96,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathObb, GetAxisY)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < numIters; ++i)
{
@ -108,7 +108,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathObb, GetAxisZ)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < numIters; ++i)
{
@ -120,7 +120,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathObb, GetAxisIndex3)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < numIters; ++i)
{
@ -136,7 +136,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathObb, SetHalfLengthX)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < numIters; ++i)
{
@ -148,7 +148,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathObb, GetHalfLengthX)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < numIters; ++i)
{
@ -160,7 +160,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathObb, SetHalfLengthY)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < numIters; ++i)
{
@ -172,7 +172,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathObb, GetHalfLengthY)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < numIters; ++i)
{
@ -184,7 +184,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathObb, SetHalfLengthZ)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < numIters; ++i)
{
@ -196,7 +196,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathObb, GetHalfLengthZ)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < numIters; ++i)
{
@ -208,7 +208,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathObb, SetHalfLengthIndex3)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < numIters; ++i)
{
@ -222,7 +222,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathObb, GetHalfLengthIndex3)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < numIters; ++i)
{
@ -242,7 +242,7 @@ namespace Benchmark
AZ::Vector3 max(120.0f, 300.0f, 50.0f);
AZ::Aabb aabb = AZ::Aabb::CreateFromMinMax(min, max);
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < numIters; ++i)
{
@ -256,7 +256,7 @@ namespace Benchmark
{
AZ::Transform transform = AZ::Transform::CreateRotationY(AZ::DegToRad(90.0f));
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < numIters; ++i)
{
@ -268,7 +268,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathObb, Equal)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < numIters; ++i)
{
@ -280,7 +280,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathObb, IsFinite)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < numIters; ++i)
{

@ -73,7 +73,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathPlane, CreateFromNormalAndDistance)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < m_numIters; ++i)
{
@ -85,7 +85,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathPlane, GetDistance)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < m_numIters; ++i)
{
@ -97,7 +97,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathPlane, GetNormal)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < m_numIters; ++i)
{
@ -109,7 +109,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathPlane, CreateFromNormalAndPoint)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < m_numIters; ++i)
{
@ -128,7 +128,7 @@ namespace Benchmark
coeff.push_back(unif(rng));
}
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < m_numIters; ++i)
{
@ -148,7 +148,7 @@ namespace Benchmark
coeff.push_back(unif(rng));
}
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < m_numIters; ++i)
{
@ -160,7 +160,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathPlane, SetVector3)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < m_numIters; ++i)
{
@ -179,7 +179,7 @@ namespace Benchmark
vecs.push_back(AZ::Vector4(unif(rng), unif(rng), unif(rng), unif(rng)));
}
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < m_numIters; ++i)
{
@ -192,7 +192,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathPlane, SetNormal)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < m_numIters; ++i)
{
@ -205,7 +205,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathPlane, SetDistance)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < m_numIters; ++i)
{
@ -218,7 +218,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathPlane, GetPlaneEquationCoefficients)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < m_numIters; ++i)
{
@ -236,7 +236,7 @@ namespace Benchmark
trans.push_back(AZ::Transform::CreateRotationY(AZ::DegToRad(unif(rng))));
}
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < m_numIters; ++i)
{
@ -254,7 +254,7 @@ namespace Benchmark
trans.push_back(AZ::Transform::CreateRotationY(AZ::DegToRad(unif(rng))));
}
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < m_numIters; ++i)
{
@ -265,7 +265,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathPlane, GetPointDist)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < m_numIters; ++i)
{
@ -277,7 +277,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathPlane, GetProjected)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < m_numIters; ++i)
{
@ -291,7 +291,7 @@ namespace Benchmark
{
AZ::Vector3 rayResult;
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < m_numIters; ++i)
{
@ -305,7 +305,7 @@ namespace Benchmark
{
float rayResult;
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < m_numIters; ++i)
{
@ -319,7 +319,7 @@ namespace Benchmark
{
AZ::Vector3 rayResult;
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < m_numIters - 1; ++i)
{
@ -333,7 +333,7 @@ namespace Benchmark
{
float rayResult;
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < m_numIters - 1; ++i)
{
@ -345,7 +345,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathPlane, IsFinite)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (int i = 0; i < m_numIters; ++i)
{

@ -68,7 +68,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, SplatFloatConstruction)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -80,7 +80,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, NonNormalized4FloatsConstruction)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -92,7 +92,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, CreateFromIdentity)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for ([[maybe_unused]] auto& quatData : m_quatDataArray)
{
@ -104,7 +104,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, CreateZero)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for ([[maybe_unused]] auto& quatData : m_quatDataArray)
{
@ -116,7 +116,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, CreateRotationX)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -128,7 +128,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, CreateRotationY)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -140,7 +140,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, CreateRotationZ)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -155,7 +155,7 @@ namespace Benchmark
const AZ::Vector3 vec1 = AZ::Vector3(1.0f, 2.0f, 3.0f).GetNormalized();
const AZ::Vector3 vec2 = AZ::Vector3(-2.0f, 7.0f, -1.0f).GetNormalized();
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for ([[maybe_unused]] auto& quatData : m_quatDataArray)
{
@ -170,7 +170,7 @@ namespace Benchmark
const AZ::Vector3 vec1 = AZ::Vector3(1.0f, 2.0f, 3.0f).GetNormalized();
const AZ::Vector3 vec2 = AZ::Vector3(-1.0f, -2.0f, -3.0f).GetNormalized();
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for ([[maybe_unused]] auto& quatData : m_quatDataArray)
{
@ -182,7 +182,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, GetX)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -194,7 +194,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, GetY)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -206,7 +206,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, GetZ)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -218,7 +218,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, GetW)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -230,7 +230,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, SetX)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -243,7 +243,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, SetY)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -256,7 +256,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, SetZ)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -269,7 +269,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, SetW)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -282,7 +282,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, SetSplat)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -295,7 +295,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, SetAll)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -310,7 +310,7 @@ namespace Benchmark
{
AZ::Vector3 vec(5.0f, 6.0f, 7.0f);
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for ([[maybe_unused]] auto& quatData : m_quatDataArray)
{
@ -324,7 +324,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, SetArray)(benchmark::State& state)
{
const float quatArray[4] = { 5.0f, 6.0f, 7.0f, 8.0f };
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for ([[maybe_unused]] auto& quatData : m_quatDataArray)
{
@ -337,7 +337,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, SetElements)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -353,7 +353,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, GetElement)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -374,7 +374,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, GetConjugate)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -386,7 +386,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, GetInverseFast)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -398,7 +398,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, GetInverseFull)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -410,7 +410,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, Dot)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -422,7 +422,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, GetLength)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -434,7 +434,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, GetLengthEstimate)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -446,7 +446,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, GetLengthReciprocal)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -458,7 +458,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, GetLengthReciprocalEstimate)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -470,7 +470,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, GetNormalized)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -482,7 +482,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, GetNormalizedEstimate)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -494,7 +494,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, NormalizeWithLength)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -506,7 +506,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, NormalizeWithLengthEstimate)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -518,7 +518,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, Lerp)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -530,7 +530,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, NLerp)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -542,7 +542,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, Slerp)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -554,7 +554,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, OperatorEquality)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -566,7 +566,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, OperatorInequality)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -578,7 +578,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, OperatorNegate)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -590,7 +590,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, OperatorSum)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -602,7 +602,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, OperatorSub)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -614,7 +614,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, OperatorMultiply)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -626,7 +626,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, OperatorMultiplyScalar)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -638,7 +638,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, TransformVector)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -653,7 +653,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, IsClose)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -665,7 +665,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, IsIdentity)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -677,7 +677,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, GetEulerDegrees)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -689,7 +689,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, GetEulerRadians)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -701,7 +701,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, SetFromEulerRadians)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -715,7 +715,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, SetFromEulerDegrees)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -729,7 +729,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, ConvertToAxisAngle)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& quatData : m_quatDataArray)
{
@ -744,7 +744,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathQuaternion, AggregateMultiply)(::benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
AZ::Vector3 position = AZ::Vector3::CreateZero();
for (auto& quatData : m_quatDataArray)

@ -80,7 +80,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathShapeIntersection, ContainsFrustumPoint)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -103,7 +103,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathShapeIntersection, OverlapsFrustumSphere)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -120,7 +120,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathShapeIntersection, ContainsFrustumSphere)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -137,7 +137,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathShapeIntersection, OverlapsFrustumAabb)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -154,7 +154,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathShapeIntersection, ContainsFrustumAabb)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{

@ -78,7 +78,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, CreateIdentity)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for ([[maybe_unused]] auto& testData : m_testDataArray)
{
@ -90,7 +90,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, CreateRotationX)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -102,7 +102,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, CreateRotationY)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -114,7 +114,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, CreateRotationZ)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -126,7 +126,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, CreateFromQuaternion)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -138,7 +138,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, CreateFromQuaternionAndTranslation)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -150,7 +150,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, CreateFromMatrix3x3)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -162,7 +162,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, CreateFromMatrix3x3AndTranslation)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -174,7 +174,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, CreateFromMatrix3x4)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -186,7 +186,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, CreateUniformScale)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -198,7 +198,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, CreateFromTranslation)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -210,7 +210,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, CreateLookAt)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -223,7 +223,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, GetBasis)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -235,7 +235,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, GetBasisX)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -247,7 +247,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, GetBasisY)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -259,7 +259,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, GetBasisZ)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -271,7 +271,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, GetBasisAndTranslation)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -287,7 +287,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, GetTranslation)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -299,7 +299,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, SetTranslationWithFloats)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -312,7 +312,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, SetTranslationWithVector3)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -325,7 +325,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, GetRotation)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -337,7 +337,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, SetRotation)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -350,7 +350,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, GetUniformScale)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -362,7 +362,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, SetUniformScale)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -375,7 +375,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, ExtractUniformScale)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -388,7 +388,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, OperatorMultiplyTransform)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -400,7 +400,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, OperatorMultiplyEqualsTransform)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -413,7 +413,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, TransformPointVector3)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -425,7 +425,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, TransformPointVector4)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -437,7 +437,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, TransformVector)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -449,7 +449,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, GetInverse)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -461,7 +461,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, Invert)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -474,7 +474,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, IsOrthogonal)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -486,7 +486,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, GetOrthogonalized)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -498,7 +498,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, Orthogonalize)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -511,7 +511,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, IsCloseExactAndDifferent)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -526,7 +526,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, OperatorEqualEqual)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -538,7 +538,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, OperatorNotEqual)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -550,7 +550,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, GetEulerDegrees)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -562,7 +562,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, GetEulerRadians)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -574,7 +574,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, SetFromEulerDegrees)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -587,7 +587,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, SetFromEulerRadians)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{
@ -600,7 +600,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathTransform, IsFinite)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& testData : m_testDataArray)
{

@ -58,7 +58,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, GetSet)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
AZ::Vector2 v1, v2;
float x = 0.0f, y = 0.0f;
@ -84,7 +84,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, ElementAccess)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
AZ::Vector2 v1, v2;
float x = 0.0f, y = 0.0f;
@ -111,7 +111,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, CreateSelectCmpEqual)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -123,7 +123,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, CreateSelectCmpGreaterEqual)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -135,7 +135,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, CreateSelectCmpGreater)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -147,7 +147,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, GetNormalized)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -159,7 +159,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, GetNormalizedEstimate)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -171,7 +171,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, NormalizeWithLength)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -183,7 +183,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, NormalizeWithLengthEstimate)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -195,7 +195,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, GetNormalizedSafe)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -207,7 +207,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, GetNormalizedSafeEstimate)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -219,7 +219,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, GetDistance)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -231,7 +231,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, GetDistanceEstimate)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -243,7 +243,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, Lerp)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -267,7 +267,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, Slerp)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -291,7 +291,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, Nlerp)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -315,7 +315,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, Dot)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -327,7 +327,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, Equality)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -339,7 +339,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, Inequality)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -351,7 +351,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, IsLessThan)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -363,7 +363,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, IsLessEqualThan)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -375,7 +375,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, IsGreaterThan)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -387,7 +387,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, IsGreaterEqualThan)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -399,7 +399,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, GetMin)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -411,7 +411,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, GetMax)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -423,7 +423,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, GetClamp)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -435,7 +435,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, Sub)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -447,7 +447,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, Sum)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -459,7 +459,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, Mul)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -471,7 +471,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, Div)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -483,7 +483,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, GetSin)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -495,7 +495,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, GetCos)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -507,7 +507,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, GetSinCos)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -521,7 +521,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, GetAcos)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -533,7 +533,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, GetAtan)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -545,7 +545,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, GetAtan2)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -557,7 +557,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, GetAngleMod)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -569,7 +569,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, Angle)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -581,7 +581,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, AngleDeg)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -593,7 +593,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, GetAbs)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -605,7 +605,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, GetReciprocal)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -617,7 +617,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, GetReciprocalEstimate)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{
@ -629,7 +629,7 @@ namespace Benchmark
BENCHMARK_F(BM_MathVector2, GetProjected)(benchmark::State& state)
{
for (auto _ : state)
for ([[maybe_unused]] auto _ : state)
{
for (auto& vecData : m_vecDataArray)
{

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save